mirror of
https://github.com/pnp/sp-dev-fx-webparts.git
synced 2025-02-28 00:39:05 +00:00
Merge branch 'main' into react-faqs
This commit is contained in:
commit
0c3a624e0f
22
.github/ISSUE_TEMPLATE/bug-report.yml
vendored
22
.github/ISSUE_TEMPLATE/bug-report.yml
vendored
@ -11,7 +11,7 @@ body:
|
||||
Thank you for reporting a bug! Use the sections below to submit a bug ONLY if it's related to samples in this repo. If you have an issue or question about the SharePoint Framework or its documentation, please submit it at https://aka.ms/spdev-issues.
|
||||
|
||||
> **IMPORTANT**
|
||||
> Before you submit an issue, please run **[spfx doctor](https://pnp.github.io/cli-microsoft365/cmd/spfx/spfx-doctor/)** from within the solution folder to diagnose incompatibility issues with your environment.
|
||||
> Before you submit an issue, please follow the **[troubleshooting steps](https://github.com/pnp/sp-dev-fx-webparts/wiki/Troubleshooting-issues-with-samples)**.
|
||||
|
||||
- Follow our guidance on [How To Create Good Issues](https://github.com/pnp/sp-dev-fx-webparts/wiki/How-to-Create-Good-Issues).
|
||||
- All bug reports are welcome - we want to fix them!
|
||||
@ -22,6 +22,15 @@ body:
|
||||
|
||||
Please provide the following details about the issue you encountered. *Issues that do not provide the information requested in this form will be flagged as **incomplete** & automatically closed.*
|
||||
|
||||
- type: dropdown
|
||||
id: disclaimer
|
||||
validations:
|
||||
required: true
|
||||
attributes:
|
||||
label: Disclaimer
|
||||
description: I have read and understood the **[support guidelines](https://github.com/pnp/sp-dev-fx-webparts/blob/main/SUPPORT.md)**, and followed the steps listed in **[troubleshooting steps](https://github.com/pnp/sp-dev-fx-webparts/wiki/Troubleshooting-issues-with-samples)** and **[how to create good issues](https://github.com/pnp/sp-dev-fx-webparts/wiki/How-to-Create-Good-Issues)** before submitting this issue. I understand that my issue may be closed if I do not follow the guidelines.
|
||||
options:
|
||||
- "Yes"
|
||||
- type: input
|
||||
id: sample
|
||||
validations:
|
||||
@ -136,17 +145,16 @@ body:
|
||||
- label: not applicable
|
||||
- label: other (enter in the "Additional environment details" area below)
|
||||
|
||||
- type: input
|
||||
id: Node
|
||||
- type: textarea
|
||||
id: spfxdoctor
|
||||
validations:
|
||||
required: true
|
||||
attributes:
|
||||
label: Node.js version
|
||||
placeholder: E.g. v10.23.1
|
||||
label: Paste the results of SPFx doctor
|
||||
description: |
|
||||
Which version of Node.js are you using?
|
||||
Run `m365 spfx doctor -o json` and paste the results.
|
||||
|
||||
TIP: To find out, run `node -v`
|
||||
Follow [the steps](https://github.com/pnp/sp-dev-fx-webparts/wiki/Troubleshooting-issues-with-samples#run-spfx-doctor) listed in [troubleshooting issues with samples](https://github.com/pnp/sp-dev-fx-webparts/wiki/Troubleshooting-issues-with-samples)
|
||||
|
||||
- type: textarea
|
||||
id: moar
|
||||
|
10
.github/ISSUE_TEMPLATE/question.yml
vendored
10
.github/ISSUE_TEMPLATE/question.yml
vendored
@ -18,6 +18,16 @@ body:
|
||||
- Screenshots are always helpful (just paste any images right here in the question)
|
||||
- If you're trying to start a conversation on a topic, consider using [Discussions](https://github.com/pnp/sp-dev-fx-webparts/discussions). We want to close every issue as quickly as possible, but discussions are intended for longer conversations.
|
||||
|
||||
|
||||
- type: dropdown
|
||||
id: disclaimer
|
||||
validations:
|
||||
required: true
|
||||
attributes:
|
||||
label: Disclaimer
|
||||
description: I have read and understood the **[support guidelines](https://github.com/pnp/sp-dev-fx-webparts/blob/main/SUPPORT.md)** before submitting this issue. I understand that my issue may be closed if I do not follow the guidelines.
|
||||
options:
|
||||
- "Yes"
|
||||
- type: input
|
||||
id: sample
|
||||
validations:
|
||||
|
9
.github/ISSUE_TEMPLATE/samplerequest.yml
vendored
9
.github/ISSUE_TEMPLATE/samplerequest.yml
vendored
@ -16,6 +16,15 @@ body:
|
||||
- If you have multiple requests submit them separately so we can track resolution.
|
||||
- We accept pull requests. If you know how to make it - go ahead! If you're unsure how to do a pull request, consider signing up for a free [Sharing is Caring First-Time Contributor](http://aka.ms/sharing-is-caring#pnp-sic-first-time-contributor) session.
|
||||
|
||||
- type: dropdown
|
||||
id: disclaimer
|
||||
validations:
|
||||
required: true
|
||||
attributes:
|
||||
label: Disclaimer
|
||||
description: I have read and understood the **[support guidelines](https://github.com/pnp/sp-dev-fx-webparts/blob/main/SUPPORT.md)** before submitting this issue. I understand that my issue may be closed if I do not follow the guidelines.
|
||||
options:
|
||||
- "Yes"
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
|
9
.github/ISSUE_TEMPLATE/suggestion.yml
vendored
9
.github/ISSUE_TEMPLATE/suggestion.yml
vendored
@ -16,6 +16,15 @@ body:
|
||||
- If you have multiple suggestions please submit them separately so we can track resolution.
|
||||
- Screenshots are always helpful (just paste any images right here in the suggestion)
|
||||
|
||||
- type: dropdown
|
||||
id: disclaimer
|
||||
validations:
|
||||
required: true
|
||||
attributes:
|
||||
label: Disclaimer
|
||||
description: I have read and understood the **[support guidelines](https://github.com/pnp/sp-dev-fx-webparts/blob/main/SUPPORT.md)** before submitting this issue. I understand that my issue may be closed if I do not follow the guidelines.
|
||||
options:
|
||||
- "Yes"
|
||||
- type: input
|
||||
id: sample
|
||||
validations:
|
||||
|
1
.github/PULL_REQUEST_TEMPLATE.md
vendored
1
.github/PULL_REQUEST_TEMPLATE.md
vendored
@ -2,6 +2,7 @@
|
||||
|
||||
> If you aren't familiar with how to contribute to open-source repositories using GitHub, or if you find the instructions on this page confusing, [sign up](https://forms.office.com/Pages/ResponsePage.aspx?id=KtIy2vgLW0SOgZbwvQuRaXDXyCl9DkBHq4A2OG7uLpdUREZVRDVYUUJLT1VNRDM4SjhGMlpUNzBORy4u) for one of our [Sharing is Caring](https://pnp.github.io/sharing-is-caring/#pnp-sic-events) events. It's completely free, and we'll guide you through the process.
|
||||
|
||||
> To submit a pull request with multiple authors, make sure that at least one commit is a co-authored commit by adding a `Co-authored-by:` trailer to the commit's message. E.g.: `Co-authored-by: name <name@example.com>`
|
||||
|
||||
| Q | A |
|
||||
| --------------- | --------------------------------------- |
|
||||
|
4
.github/label-actions.yml
vendored
4
.github/label-actions.yml
vendored
@ -63,9 +63,9 @@ status:node-compatibility:
|
||||
comment: |+
|
||||
Thank you for your issue. It looks like the web part sample you're trying to use is not compatible with the version of Node.js that you're running in your environment.
|
||||
|
||||
Please refer to the [SPFx Compatibility Matrix](https://docs.microsoft.com/en-us/sharepoint/dev/spfx/compatibility) to make sure that you're using a version of Node.js that is compatible with the version of SPFx the sample uses.
|
||||
You should refer to [the troubleshooting instructons](https://github.com/pnp/sp-dev-fx-webparts/wiki/Troubleshooting-issues-with-samples) **before** opening an issue to make sure that you have eliminated the most common causes.
|
||||
|
||||
We'll close this issue, but if you run into further issues after you have made changes to your environment, please do not hesitate to open a new issue so we can help you further.
|
||||
We'll close this issue, but if you run into further issues after you have made changes to your environment and followed the [troubreshooting steps](https://github.com/pnp/sp-dev-fx-webparts/wiki/Troubleshooting-issues-with-samples), please do not hesitate to open a new issue so we can help you further.
|
||||
|
||||
# Close the issue
|
||||
close: true
|
||||
|
34
.github/workflows/close-stale-issues.yml
vendored
Normal file
34
.github/workflows/close-stale-issues.yml
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
name: 'Close stale issues'
|
||||
on:
|
||||
schedule:
|
||||
- cron: '30 1 * * *'
|
||||
workflow_dispatch:
|
||||
permissions:
|
||||
issues: write
|
||||
jobs:
|
||||
destale-inator:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/stale@v4
|
||||
name: 'Close invalid authors'
|
||||
with:
|
||||
days-before-issue-stale: 3
|
||||
days-before-issue-close: 1
|
||||
days-before-pr-stale: -1
|
||||
operations-per-run: 1000
|
||||
stale-issue-message: 'Please note that this issue will be closed within 24 hours because it has been flagged as having invalid authors. [Read the guidance](https://github.com/pnp/sp-dev-fx-webparts/wiki/How-to-create-good-issues#mention-authors) and @mention the authors so they can respond to you.'
|
||||
only-issue-labels: 'status:wrong-author'
|
||||
close-issue-message: 'Closing this issue due to lack of response. Feel free to open a new issue, but make sure to follow the guidance on [how to create good issues](https://github.com/pnp/sp-dev-fx-webparts/wiki/How-to-create-good-issues#mention-authors) and @mention the authors so they can respond to you.'
|
||||
- uses: actions/stale@v4
|
||||
name: 'Close stale issues'
|
||||
with:
|
||||
days-before-issue-stale: 90
|
||||
days-before-issue-close: 7
|
||||
days-before-pr-stale: -1
|
||||
stale-issue-label: 'status:no-recent-activity'
|
||||
exempt-all-issue-assignees: true
|
||||
exempt-issue-labels: 'type:sample-request'
|
||||
remove-issue-stale-when-updated: true
|
||||
operations-per-run: 1000
|
||||
stale-issue-message: 'This issue has been marked as stale due to no progress in over 90 days. If you are still experiencing this issue, please provide additional information so we can help you resolve it.'
|
||||
close-issue-message: 'Closing this issue due to lack of activity. If you are still encountering this issue, please do not hesitate to open a new issue. Make sure to follow the guidance on [how to create good issues](https://github.com/pnp/sp-dev-fx-webparts/wiki/How-to-create-good-issues) to increase your chances of getting the help you deserve.'
|
39
samples/angular-multipage/.devcontainer/devcontainer.json
Normal file
39
samples/angular-multipage/.devcontainer/devcontainer.json
Normal file
@ -0,0 +1,39 @@
|
||||
// For more information on how to run this SPFx project in a VS Code Remote Container, please visit https://aka.ms/spfx-devcontainer
|
||||
{
|
||||
"name": "SPFx 0.4.0",
|
||||
"image": "docker.io/m365pnp/spfx:0.4.0",
|
||||
// Set *default* container specific settings.json values on container create.
|
||||
"settings": {},
|
||||
// Add the IDs of extensions you want installed when the container is created.
|
||||
"extensions": [
|
||||
"editorconfig.editorconfig",
|
||||
"dbaeumer.vscode-eslint"
|
||||
],
|
||||
// Use 'forwardPorts' to make a list of ports inside the container available locally.
|
||||
"forwardPorts": [
|
||||
4321,
|
||||
35729,
|
||||
5432
|
||||
],
|
||||
"portsAttributes": {
|
||||
"4321": {
|
||||
"protocol": "https",
|
||||
"label": "Manifest",
|
||||
"onAutoForward": "silent",
|
||||
"requireLocalPort": true
|
||||
},
|
||||
"5432": {
|
||||
"protocol": "https",
|
||||
"label": "Workbench",
|
||||
"onAutoForward": "silent"
|
||||
},
|
||||
"35729": {
|
||||
"protocol": "https",
|
||||
"label": "LiveReload",
|
||||
"onAutoForward": "silent",
|
||||
"requireLocalPort": true
|
||||
}
|
||||
},
|
||||
"postCreateCommand": "bash .devcontainer/spfx-startup.sh",
|
||||
"remoteUser": "node"
|
||||
}
|
31
samples/angular-multipage/.devcontainer/spfx-startup.sh
Normal file
31
samples/angular-multipage/.devcontainer/spfx-startup.sh
Normal file
@ -0,0 +1,31 @@
|
||||
echo
|
||||
echo -e "\e[1;94mInstalling Node dependencies\e[0m"
|
||||
npm install
|
||||
|
||||
## commands to create dev certificate and copy it to the root folder of the project
|
||||
echo
|
||||
echo -e "\e[1;94mGenerating dev certificate\e[0m"
|
||||
gulp trust-dev-cert
|
||||
|
||||
|
||||
cp ~/.gcb-serve-data/gcb-serve.cer ./spfx-dev-cert.cer
|
||||
cp ~/.gcb-serve-data/gcb-serve.cer ./spfx-dev-cert.pem
|
||||
|
||||
## add *.cer to .gitignore to prevent certificates from being saved in repo
|
||||
if ! grep -Fxq '*.cer' ./.gitignore
|
||||
then
|
||||
echo "# .CER Certificates" >> .gitignore
|
||||
echo "*.cer" >> .gitignore
|
||||
fi
|
||||
|
||||
## add *.pem to .gitignore to prevent certificates from being saved in repo
|
||||
if ! grep -Fxq '*.pem' ./.gitignore
|
||||
then
|
||||
echo "# .PEM Certificates" >> .gitignore
|
||||
echo "*.pem" >> .gitignore
|
||||
fi
|
||||
|
||||
echo
|
||||
echo -e "\e[1;92mReady!\e[0m"
|
||||
|
||||
echo -e "\n\e[1;94m**********\nOptional: if you plan on using gulp serve, don't forget to add the container certificate to your local machine. Please visit https://aka.ms/spfx-devcontainer for more information\n**********"
|
@ -34,6 +34,7 @@ This sample contains a poll web part allowing users to vote and view the results
|
||||
-Compatible-green.svg)
|
||||

|
||||

|
||||

|
||||
|
||||
|
||||
## Applies to
|
||||
@ -61,6 +62,8 @@ Version|Date|Comments
|
||||
|
||||
### Poll web part
|
||||
|
||||
> This sample can also be opened with [VS Code Remote Development](https://code.visualstudio.com/docs/remote/remote-overview). Visit https://aka.ms/spfx-devcontainer for further instructions.
|
||||
|
||||
- create list for the poll
|
||||
- in SharePoint create a new list
|
||||
- in the list add new column called `NumVotes` of type **Number** (you can change the name later if you want)
|
||||
|
39
samples/angular-search/.devcontainer/devcontainer.json
Normal file
39
samples/angular-search/.devcontainer/devcontainer.json
Normal file
@ -0,0 +1,39 @@
|
||||
// For more information on how to run this SPFx project in a VS Code Remote Container, please visit https://aka.ms/spfx-devcontainer
|
||||
{
|
||||
"name": "SPFx 0.1.2",
|
||||
"image": "docker.io/m365pnp/spfx:0.1.2",
|
||||
// Set *default* container specific settings.json values on container create.
|
||||
"settings": {},
|
||||
// Add the IDs of extensions you want installed when the container is created.
|
||||
"extensions": [
|
||||
"editorconfig.editorconfig",
|
||||
"dbaeumer.vscode-eslint"
|
||||
],
|
||||
// Use 'forwardPorts' to make a list of ports inside the container available locally.
|
||||
"forwardPorts": [
|
||||
4321,
|
||||
35729,
|
||||
5432
|
||||
],
|
||||
"portsAttributes": {
|
||||
"4321": {
|
||||
"protocol": "https",
|
||||
"label": "Manifest",
|
||||
"onAutoForward": "silent",
|
||||
"requireLocalPort": true
|
||||
},
|
||||
"5432": {
|
||||
"protocol": "https",
|
||||
"label": "Workbench",
|
||||
"onAutoForward": "silent"
|
||||
},
|
||||
"35729": {
|
||||
"protocol": "https",
|
||||
"label": "LiveReload",
|
||||
"onAutoForward": "silent",
|
||||
"requireLocalPort": true
|
||||
}
|
||||
},
|
||||
"postCreateCommand": "bash .devcontainer/spfx-startup.sh",
|
||||
"remoteUser": "node"
|
||||
}
|
31
samples/angular-search/.devcontainer/spfx-startup.sh
Normal file
31
samples/angular-search/.devcontainer/spfx-startup.sh
Normal file
@ -0,0 +1,31 @@
|
||||
echo
|
||||
echo -e "\e[1;94mInstalling Node dependencies\e[0m"
|
||||
npm install
|
||||
|
||||
## commands to create dev certificate and copy it to the root folder of the project
|
||||
echo
|
||||
echo -e "\e[1;94mGenerating dev certificate\e[0m"
|
||||
gulp trust-dev-cert
|
||||
|
||||
|
||||
cp ~/.gcb-serve-data/gcb-serve.cer ./spfx-dev-cert.cer
|
||||
cp ~/.gcb-serve-data/gcb-serve.cer ./spfx-dev-cert.pem
|
||||
|
||||
## add *.cer to .gitignore to prevent certificates from being saved in repo
|
||||
if ! grep -Fxq '*.cer' ./.gitignore
|
||||
then
|
||||
echo "# .CER Certificates" >> .gitignore
|
||||
echo "*.cer" >> .gitignore
|
||||
fi
|
||||
|
||||
## add *.pem to .gitignore to prevent certificates from being saved in repo
|
||||
if ! grep -Fxq '*.pem' ./.gitignore
|
||||
then
|
||||
echo "# .PEM Certificates" >> .gitignore
|
||||
echo "*.pem" >> .gitignore
|
||||
fi
|
||||
|
||||
echo
|
||||
echo -e "\e[1;92mReady!\e[0m"
|
||||
|
||||
echo -e "\n\e[1;94m**********\nOptional: if you plan on using gulp serve, don't forget to add the container certificate to your local machine. Please visit https://aka.ms/spfx-devcontainer for more information\n**********"
|
@ -41,6 +41,7 @@ The logic for querying the SharePoint Content Types in the properties of the web
|
||||
-Compatible-green.svg)
|
||||

|
||||

|
||||

|
||||
|
||||
|
||||
## Applies to
|
||||
|
39
samples/angular2-prototype/.devcontainer/devcontainer.json
Normal file
39
samples/angular2-prototype/.devcontainer/devcontainer.json
Normal file
@ -0,0 +1,39 @@
|
||||
// For more information on how to run this SPFx project in a VS Code Remote Container, please visit https://aka.ms/spfx-devcontainer
|
||||
{
|
||||
"name": "SPFx 0.1.2",
|
||||
"image": "docker.io/m365pnp/spfx:0.1.2",
|
||||
// Set *default* container specific settings.json values on container create.
|
||||
"settings": {},
|
||||
// Add the IDs of extensions you want installed when the container is created.
|
||||
"extensions": [
|
||||
"editorconfig.editorconfig",
|
||||
"dbaeumer.vscode-eslint"
|
||||
],
|
||||
// Use 'forwardPorts' to make a list of ports inside the container available locally.
|
||||
"forwardPorts": [
|
||||
4321,
|
||||
35729,
|
||||
5432
|
||||
],
|
||||
"portsAttributes": {
|
||||
"4321": {
|
||||
"protocol": "https",
|
||||
"label": "Manifest",
|
||||
"onAutoForward": "silent",
|
||||
"requireLocalPort": true
|
||||
},
|
||||
"5432": {
|
||||
"protocol": "https",
|
||||
"label": "Workbench",
|
||||
"onAutoForward": "silent"
|
||||
},
|
||||
"35729": {
|
||||
"protocol": "https",
|
||||
"label": "LiveReload",
|
||||
"onAutoForward": "silent",
|
||||
"requireLocalPort": true
|
||||
}
|
||||
},
|
||||
"postCreateCommand": "bash .devcontainer/spfx-startup.sh",
|
||||
"remoteUser": "node"
|
||||
}
|
31
samples/angular2-prototype/.devcontainer/spfx-startup.sh
Normal file
31
samples/angular2-prototype/.devcontainer/spfx-startup.sh
Normal file
@ -0,0 +1,31 @@
|
||||
echo
|
||||
echo -e "\e[1;94mInstalling Node dependencies\e[0m"
|
||||
npm install
|
||||
|
||||
## commands to create dev certificate and copy it to the root folder of the project
|
||||
echo
|
||||
echo -e "\e[1;94mGenerating dev certificate\e[0m"
|
||||
gulp trust-dev-cert
|
||||
|
||||
|
||||
cp ~/.gcb-serve-data/gcb-serve.cer ./spfx-dev-cert.cer
|
||||
cp ~/.gcb-serve-data/gcb-serve.cer ./spfx-dev-cert.pem
|
||||
|
||||
## add *.cer to .gitignore to prevent certificates from being saved in repo
|
||||
if ! grep -Fxq '*.cer' ./.gitignore
|
||||
then
|
||||
echo "# .CER Certificates" >> .gitignore
|
||||
echo "*.cer" >> .gitignore
|
||||
fi
|
||||
|
||||
## add *.pem to .gitignore to prevent certificates from being saved in repo
|
||||
if ! grep -Fxq '*.pem' ./.gitignore
|
||||
then
|
||||
echo "# .PEM Certificates" >> .gitignore
|
||||
echo "*.pem" >> .gitignore
|
||||
fi
|
||||
|
||||
echo
|
||||
echo -e "\e[1;92mReady!\e[0m"
|
||||
|
||||
echo -e "\n\e[1;94m**********\nOptional: if you plan on using gulp serve, don't forget to add the container certificate to your local machine. Please visit https://aka.ms/spfx-devcontainer for more information\n**********"
|
@ -38,6 +38,7 @@ Sample To Do Web Part built with Angular2. This sample illustrates how you can u
|
||||
-Compatible-green.svg)
|
||||

|
||||

|
||||

|
||||
|
||||
|
||||
|
||||
@ -75,6 +76,8 @@ Version|Date|Comments
|
||||
- Open the workbench
|
||||
- Test out the web part
|
||||
|
||||
> This sample can also be opened with [VS Code Remote Development](https://code.visualstudio.com/docs/remote/remote-overview). Visit https://aka.ms/spfx-devcontainer for further instructions.
|
||||
|
||||
## Features
|
||||
|
||||
This is a sample client-side web part built on the SharePoint Framework using Angular2 for building the UI component of the web part.
|
||||
|
39
samples/jquery-cdn/.devcontainer/devcontainer.json
Normal file
39
samples/jquery-cdn/.devcontainer/devcontainer.json
Normal file
@ -0,0 +1,39 @@
|
||||
// For more information on how to run this SPFx project in a VS Code Remote Container, please visit https://aka.ms/spfx-devcontainer
|
||||
{
|
||||
"name": "SPFx 0.2.0",
|
||||
"image": "docker.io/m365pnp/spfx:0.2.0",
|
||||
// Set *default* container specific settings.json values on container create.
|
||||
"settings": {},
|
||||
// Add the IDs of extensions you want installed when the container is created.
|
||||
"extensions": [
|
||||
"editorconfig.editorconfig",
|
||||
"dbaeumer.vscode-eslint"
|
||||
],
|
||||
// Use 'forwardPorts' to make a list of ports inside the container available locally.
|
||||
"forwardPorts": [
|
||||
4321,
|
||||
35729,
|
||||
5432
|
||||
],
|
||||
"portsAttributes": {
|
||||
"4321": {
|
||||
"protocol": "https",
|
||||
"label": "Manifest",
|
||||
"onAutoForward": "silent",
|
||||
"requireLocalPort": true
|
||||
},
|
||||
"5432": {
|
||||
"protocol": "https",
|
||||
"label": "Workbench",
|
||||
"onAutoForward": "silent"
|
||||
},
|
||||
"35729": {
|
||||
"protocol": "https",
|
||||
"label": "LiveReload",
|
||||
"onAutoForward": "silent",
|
||||
"requireLocalPort": true
|
||||
}
|
||||
},
|
||||
"postCreateCommand": "bash .devcontainer/spfx-startup.sh",
|
||||
"remoteUser": "node"
|
||||
}
|
31
samples/jquery-cdn/.devcontainer/spfx-startup.sh
Normal file
31
samples/jquery-cdn/.devcontainer/spfx-startup.sh
Normal file
@ -0,0 +1,31 @@
|
||||
echo
|
||||
echo -e "\e[1;94mInstalling Node dependencies\e[0m"
|
||||
npm install
|
||||
|
||||
## commands to create dev certificate and copy it to the root folder of the project
|
||||
echo
|
||||
echo -e "\e[1;94mGenerating dev certificate\e[0m"
|
||||
gulp trust-dev-cert
|
||||
|
||||
|
||||
cp ~/.gcb-serve-data/gcb-serve.cer ./spfx-dev-cert.cer
|
||||
cp ~/.gcb-serve-data/gcb-serve.cer ./spfx-dev-cert.pem
|
||||
|
||||
## add *.cer to .gitignore to prevent certificates from being saved in repo
|
||||
if ! grep -Fxq '*.cer' ./.gitignore
|
||||
then
|
||||
echo "# .CER Certificates" >> .gitignore
|
||||
echo "*.cer" >> .gitignore
|
||||
fi
|
||||
|
||||
## add *.pem to .gitignore to prevent certificates from being saved in repo
|
||||
if ! grep -Fxq '*.pem' ./.gitignore
|
||||
then
|
||||
echo "# .PEM Certificates" >> .gitignore
|
||||
echo "*.pem" >> .gitignore
|
||||
fi
|
||||
|
||||
echo
|
||||
echo -e "\e[1;92mReady!\e[0m"
|
||||
|
||||
echo -e "\n\e[1;94m**********\nOptional: if you plan on using gulp serve, don't forget to add the container certificate to your local machine. Please visit https://aka.ms/spfx-devcontainer for more information\n**********"
|
@ -34,6 +34,7 @@ This is a sample web Part that illustrates the use of jQuery and its plugins loa
|
||||
-Compatible-green.svg)
|
||||

|
||||

|
||||

|
||||
|
||||
## Applies to
|
||||
|
||||
@ -59,6 +60,8 @@ Version|Date|Comments
|
||||
- `npm i`
|
||||
- `gulp serve`
|
||||
|
||||
> This sample can also be opened with [VS Code Remote Development](https://code.visualstudio.com/docs/remote/remote-overview). Visit https://aka.ms/spfx-devcontainer for further instructions.
|
||||
|
||||
## Features
|
||||
|
||||
This project contains sample client-side web parts built on the SharePoint Framework illustrating how to use jQuery and its plugins loaded from CDN for building SharePoint Framework client-side web parts.
|
||||
|
39
samples/js-extend-gulp/.devcontainer/devcontainer.json
Normal file
39
samples/js-extend-gulp/.devcontainer/devcontainer.json
Normal file
@ -0,0 +1,39 @@
|
||||
// For more information on how to run this SPFx project in a VS Code Remote Container, please visit https://aka.ms/spfx-devcontainer
|
||||
{
|
||||
"name": "SPFx 0.1.2",
|
||||
"image": "docker.io/m365pnp/spfx:0.1.2",
|
||||
// Set *default* container specific settings.json values on container create.
|
||||
"settings": {},
|
||||
// Add the IDs of extensions you want installed when the container is created.
|
||||
"extensions": [
|
||||
"editorconfig.editorconfig",
|
||||
"dbaeumer.vscode-eslint"
|
||||
],
|
||||
// Use 'forwardPorts' to make a list of ports inside the container available locally.
|
||||
"forwardPorts": [
|
||||
4321,
|
||||
35729,
|
||||
5432
|
||||
],
|
||||
"portsAttributes": {
|
||||
"4321": {
|
||||
"protocol": "https",
|
||||
"label": "Manifest",
|
||||
"onAutoForward": "silent",
|
||||
"requireLocalPort": true
|
||||
},
|
||||
"5432": {
|
||||
"protocol": "https",
|
||||
"label": "Workbench",
|
||||
"onAutoForward": "silent"
|
||||
},
|
||||
"35729": {
|
||||
"protocol": "https",
|
||||
"label": "LiveReload",
|
||||
"onAutoForward": "silent",
|
||||
"requireLocalPort": true
|
||||
}
|
||||
},
|
||||
"postCreateCommand": "bash .devcontainer/spfx-startup.sh",
|
||||
"remoteUser": "node"
|
||||
}
|
31
samples/js-extend-gulp/.devcontainer/spfx-startup.sh
Normal file
31
samples/js-extend-gulp/.devcontainer/spfx-startup.sh
Normal file
@ -0,0 +1,31 @@
|
||||
echo
|
||||
echo -e "\e[1;94mInstalling Node dependencies\e[0m"
|
||||
npm install
|
||||
|
||||
## commands to create dev certificate and copy it to the root folder of the project
|
||||
echo
|
||||
echo -e "\e[1;94mGenerating dev certificate\e[0m"
|
||||
gulp trust-dev-cert
|
||||
|
||||
|
||||
cp ~/.gcb-serve-data/gcb-serve.cer ./spfx-dev-cert.cer
|
||||
cp ~/.gcb-serve-data/gcb-serve.cer ./spfx-dev-cert.pem
|
||||
|
||||
## add *.cer to .gitignore to prevent certificates from being saved in repo
|
||||
if ! grep -Fxq '*.cer' ./.gitignore
|
||||
then
|
||||
echo "# .CER Certificates" >> .gitignore
|
||||
echo "*.cer" >> .gitignore
|
||||
fi
|
||||
|
||||
## add *.pem to .gitignore to prevent certificates from being saved in repo
|
||||
if ! grep -Fxq '*.pem' ./.gitignore
|
||||
then
|
||||
echo "# .PEM Certificates" >> .gitignore
|
||||
echo "*.pem" >> .gitignore
|
||||
fi
|
||||
|
||||
echo
|
||||
echo -e "\e[1;92mReady!\e[0m"
|
||||
|
||||
echo -e "\n\e[1;94m**********\nOptional: if you plan on using gulp serve, don't forget to add the container certificate to your local machine. Please visit https://aka.ms/spfx-devcontainer for more information\n**********"
|
@ -39,6 +39,7 @@ Read the following documentation for detailed information on integrating gulp ta
|
||||
-Compatible-green.svg)
|
||||

|
||||

|
||||

|
||||
|
||||
|
||||
|
||||
@ -91,6 +92,8 @@ Version|Date|Comments
|
||||
- `npm install`
|
||||
- `gulp serve`
|
||||
|
||||
> This sample can also be opened with [VS Code Remote Development](https://code.visualstudio.com/docs/remote/remote-overview). Visit https://aka.ms/spfx-devcontainer for further instructions.
|
||||
|
||||
## Help
|
||||
|
||||
We do not support samples, but 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.
|
||||
|
39
samples/js-powerbi-embedded/.devcontainer/devcontainer.json
Normal file
39
samples/js-powerbi-embedded/.devcontainer/devcontainer.json
Normal file
@ -0,0 +1,39 @@
|
||||
// For more information on how to run this SPFx project in a VS Code Remote Container, please visit https://aka.ms/spfx-devcontainer
|
||||
{
|
||||
"name": "SPFx 0.2.0",
|
||||
"image": "docker.io/m365pnp/spfx:0.2.0",
|
||||
// Set *default* container specific settings.json values on container create.
|
||||
"settings": {},
|
||||
// Add the IDs of extensions you want installed when the container is created.
|
||||
"extensions": [
|
||||
"editorconfig.editorconfig",
|
||||
"dbaeumer.vscode-eslint"
|
||||
],
|
||||
// Use 'forwardPorts' to make a list of ports inside the container available locally.
|
||||
"forwardPorts": [
|
||||
4321,
|
||||
35729,
|
||||
5432
|
||||
],
|
||||
"portsAttributes": {
|
||||
"4321": {
|
||||
"protocol": "https",
|
||||
"label": "Manifest",
|
||||
"onAutoForward": "silent",
|
||||
"requireLocalPort": true
|
||||
},
|
||||
"5432": {
|
||||
"protocol": "https",
|
||||
"label": "Workbench",
|
||||
"onAutoForward": "silent"
|
||||
},
|
||||
"35729": {
|
||||
"protocol": "https",
|
||||
"label": "LiveReload",
|
||||
"onAutoForward": "silent",
|
||||
"requireLocalPort": true
|
||||
}
|
||||
},
|
||||
"postCreateCommand": "bash .devcontainer/spfx-startup.sh",
|
||||
"remoteUser": "node"
|
||||
}
|
31
samples/js-powerbi-embedded/.devcontainer/spfx-startup.sh
Normal file
31
samples/js-powerbi-embedded/.devcontainer/spfx-startup.sh
Normal file
@ -0,0 +1,31 @@
|
||||
echo
|
||||
echo -e "\e[1;94mInstalling Node dependencies\e[0m"
|
||||
npm install
|
||||
|
||||
## commands to create dev certificate and copy it to the root folder of the project
|
||||
echo
|
||||
echo -e "\e[1;94mGenerating dev certificate\e[0m"
|
||||
gulp trust-dev-cert
|
||||
|
||||
|
||||
cp ~/.gcb-serve-data/gcb-serve.cer ./spfx-dev-cert.cer
|
||||
cp ~/.gcb-serve-data/gcb-serve.cer ./spfx-dev-cert.pem
|
||||
|
||||
## add *.cer to .gitignore to prevent certificates from being saved in repo
|
||||
if ! grep -Fxq '*.cer' ./.gitignore
|
||||
then
|
||||
echo "# .CER Certificates" >> .gitignore
|
||||
echo "*.cer" >> .gitignore
|
||||
fi
|
||||
|
||||
## add *.pem to .gitignore to prevent certificates from being saved in repo
|
||||
if ! grep -Fxq '*.pem' ./.gitignore
|
||||
then
|
||||
echo "# .PEM Certificates" >> .gitignore
|
||||
echo "*.pem" >> .gitignore
|
||||
fi
|
||||
|
||||
echo
|
||||
echo -e "\e[1;92mReady!\e[0m"
|
||||
|
||||
echo -e "\n\e[1;94m**********\nOptional: if you plan on using gulp serve, don't forget to add the container certificate to your local machine. Please visit https://aka.ms/spfx-devcontainer for more information\n**********"
|
@ -32,6 +32,7 @@ This sample SharePoint Framework client-side web part embedding a PowerBI report
|
||||
-Compatible-green.svg)
|
||||

|
||||

|
||||

|
||||
|
||||
## Solution
|
||||
|
||||
@ -60,6 +61,8 @@ Please refer to [this blog post](http://rolandoldengarm.com/index.php/2016/09/13
|
||||
- `$ npm i`
|
||||
- `$ gulp serve`
|
||||
|
||||
> This sample can also be opened with [VS Code Remote Development](https://code.visualstudio.com/docs/remote/remote-overview). Visit https://aka.ms/spfx-devcontainer for further instructions.
|
||||
|
||||
## Features
|
||||
|
||||
The _PowerBI Embedded_ Client-Side Web Part is built on the SharePoint Framework using React and uses [PowerBI Embedded](https://azure.microsoft.com/en-us/services/power-bi-embedded/) to securely display a report.
|
||||
|
6
samples/js-teams-meeting-app/package-lock.json
generated
6
samples/js-teams-meeting-app/package-lock.json
generated
@ -19607,9 +19607,9 @@
|
||||
}
|
||||
},
|
||||
"url-parse": {
|
||||
"version": "1.5.8",
|
||||
"resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.8.tgz",
|
||||
"integrity": "sha512-9JZ5zDrn9wJoOy/t+rH00HHejbU8dq9VsOYVu272TYDrCiyVAgHKUSpPh3ruZIpv8PMVR+NXLZvfRPJv8xAcQw==",
|
||||
"version": "1.5.10",
|
||||
"resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz",
|
||||
"integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"querystringify": "^2.1.1",
|
||||
|
@ -15,7 +15,7 @@
|
||||
<package id="Microsoft.Azure.ActiveDirectory.GraphClient" version="2.0.2" targetFramework="net461" />
|
||||
<package id="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" version="1.0.7" targetFramework="net461" />
|
||||
<package id="Microsoft.Data.Edm" version="5.6.3" targetFramework="net461" />
|
||||
<package id="Microsoft.Data.OData" version="5.6.3" targetFramework="net461" />
|
||||
<package id="Microsoft.Data.OData" version="5.8.4" targetFramework="net461" />
|
||||
<package id="Microsoft.Data.Services.Client" version="5.6.3" targetFramework="net461" />
|
||||
<package id="Microsoft.IdentityModel.Clients.ActiveDirectory" version="2.29.0" targetFramework="net461" />
|
||||
<package id="Microsoft.IdentityModel.Logging" version="5.2.1" targetFramework="net461" />
|
||||
|
6
samples/react-adaptivecards/package-lock.json
generated
6
samples/react-adaptivecards/package-lock.json
generated
@ -20494,9 +20494,9 @@
|
||||
}
|
||||
},
|
||||
"url-parse": {
|
||||
"version": "1.5.8",
|
||||
"resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.8.tgz",
|
||||
"integrity": "sha512-9JZ5zDrn9wJoOy/t+rH00HHejbU8dq9VsOYVu272TYDrCiyVAgHKUSpPh3ruZIpv8PMVR+NXLZvfRPJv8xAcQw==",
|
||||
"version": "1.5.10",
|
||||
"resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz",
|
||||
"integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"querystringify": "^2.1.1",
|
||||
|
6
samples/react-at-a-glance/package-lock.json
generated
6
samples/react-at-a-glance/package-lock.json
generated
@ -21932,9 +21932,9 @@
|
||||
}
|
||||
},
|
||||
"url-parse": {
|
||||
"version": "1.5.8",
|
||||
"resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.8.tgz",
|
||||
"integrity": "sha512-9JZ5zDrn9wJoOy/t+rH00HHejbU8dq9VsOYVu272TYDrCiyVAgHKUSpPh3ruZIpv8PMVR+NXLZvfRPJv8xAcQw==",
|
||||
"version": "1.5.10",
|
||||
"resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz",
|
||||
"integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"querystringify": "^2.1.1",
|
||||
|
6
samples/react-birthdays/package-lock.json
generated
6
samples/react-birthdays/package-lock.json
generated
@ -23287,9 +23287,9 @@
|
||||
}
|
||||
},
|
||||
"url-parse": {
|
||||
"version": "1.5.8",
|
||||
"resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.8.tgz",
|
||||
"integrity": "sha512-9JZ5zDrn9wJoOy/t+rH00HHejbU8dq9VsOYVu272TYDrCiyVAgHKUSpPh3ruZIpv8PMVR+NXLZvfRPJv8xAcQw==",
|
||||
"version": "1.5.10",
|
||||
"resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz",
|
||||
"integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"querystringify": "^2.1.1",
|
||||
|
6
samples/react-carousel/package-lock.json
generated
6
samples/react-carousel/package-lock.json
generated
@ -29030,9 +29030,9 @@
|
||||
}
|
||||
},
|
||||
"url-parse": {
|
||||
"version": "1.5.8",
|
||||
"resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.8.tgz",
|
||||
"integrity": "sha512-9JZ5zDrn9wJoOy/t+rH00HHejbU8dq9VsOYVu272TYDrCiyVAgHKUSpPh3ruZIpv8PMVR+NXLZvfRPJv8xAcQw==",
|
||||
"version": "1.5.10",
|
||||
"resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz",
|
||||
"integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"querystringify": "^2.1.1",
|
||||
|
@ -19645,9 +19645,9 @@
|
||||
}
|
||||
},
|
||||
"url-parse": {
|
||||
"version": "1.5.8",
|
||||
"resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.8.tgz",
|
||||
"integrity": "sha512-9JZ5zDrn9wJoOy/t+rH00HHejbU8dq9VsOYVu272TYDrCiyVAgHKUSpPh3ruZIpv8PMVR+NXLZvfRPJv8xAcQw==",
|
||||
"version": "1.5.10",
|
||||
"resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz",
|
||||
"integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"querystringify": "^2.1.1",
|
||||
|
@ -9,7 +9,7 @@
|
||||
"Sample custom property pane controls built in React for use with SharePoint Framework client-side web parts."
|
||||
],
|
||||
"creationDateTime": "2017-05-01",
|
||||
"updateDateTime": "2026-01-22",
|
||||
"updateDateTime": "2022-01-26",
|
||||
"products": [
|
||||
"SharePoint"
|
||||
],
|
||||
|
@ -21999,9 +21999,9 @@
|
||||
}
|
||||
},
|
||||
"url-parse": {
|
||||
"version": "1.5.8",
|
||||
"resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.8.tgz",
|
||||
"integrity": "sha512-9JZ5zDrn9wJoOy/t+rH00HHejbU8dq9VsOYVu272TYDrCiyVAgHKUSpPh3ruZIpv8PMVR+NXLZvfRPJv8xAcQw==",
|
||||
"version": "1.5.10",
|
||||
"resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz",
|
||||
"integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"querystringify": "^2.1.1",
|
||||
|
6
samples/react-directory/package-lock.json
generated
6
samples/react-directory/package-lock.json
generated
@ -17645,9 +17645,9 @@
|
||||
}
|
||||
},
|
||||
"lodash": {
|
||||
"version": "4.17.20",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
|
||||
"integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA=="
|
||||
"version": "4.17.21",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
|
||||
},
|
||||
"lodash._basecopy": {
|
||||
"version": "3.0.1",
|
||||
|
@ -26,7 +26,7 @@
|
||||
"@types/jquery": "^3.3.30",
|
||||
"@uifabric/fluent-theme": "^0.16.9",
|
||||
"jquery": "^3.4.1",
|
||||
"lodash": "^4.17.20",
|
||||
"lodash": "^4.17.21",
|
||||
"office-ui-fabric-react": "6.214.0",
|
||||
"react": "16.7.0",
|
||||
"react-dom": "16.7.0",
|
||||
|
@ -15170,9 +15170,9 @@
|
||||
}
|
||||
},
|
||||
"minimist": {
|
||||
"version": "1.2.5",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
|
||||
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
|
||||
"version": "1.2.6",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
|
||||
"integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q=="
|
||||
},
|
||||
"minipass": {
|
||||
"version": "3.1.5",
|
||||
@ -15361,9 +15361,9 @@
|
||||
"integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ=="
|
||||
},
|
||||
"nanoid": {
|
||||
"version": "3.1.29",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.29.tgz",
|
||||
"integrity": "sha512-dW2pUSGZ8ZnCFIlBIA31SV8huOGCHb6OwzVCc7A69rb/a+SgPBwfmLvK5TKQ3INPbRkcI8a/Owo0XbiTNH19wg==",
|
||||
"version": "3.3.1",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz",
|
||||
"integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==",
|
||||
"dev": true
|
||||
},
|
||||
"nanomatch": {
|
||||
@ -20785,9 +20785,9 @@
|
||||
}
|
||||
},
|
||||
"url-parse": {
|
||||
"version": "1.5.8",
|
||||
"resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.8.tgz",
|
||||
"integrity": "sha512-9JZ5zDrn9wJoOy/t+rH00HHejbU8dq9VsOYVu272TYDrCiyVAgHKUSpPh3ruZIpv8PMVR+NXLZvfRPJv8xAcQw==",
|
||||
"version": "1.5.10",
|
||||
"resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz",
|
||||
"integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"querystringify": "^2.1.1",
|
||||
|
6
samples/react-emoji-ratings/package-lock.json
generated
6
samples/react-emoji-ratings/package-lock.json
generated
@ -20944,9 +20944,9 @@
|
||||
}
|
||||
},
|
||||
"url-parse": {
|
||||
"version": "1.5.8",
|
||||
"resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.8.tgz",
|
||||
"integrity": "sha512-9JZ5zDrn9wJoOy/t+rH00HHejbU8dq9VsOYVu272TYDrCiyVAgHKUSpPh3ruZIpv8PMVR+NXLZvfRPJv8xAcQw==",
|
||||
"version": "1.5.10",
|
||||
"resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz",
|
||||
"integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"querystringify": "^2.1.1",
|
||||
|
@ -11857,9 +11857,9 @@
|
||||
}
|
||||
},
|
||||
"minimist": {
|
||||
"version": "1.2.5",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
|
||||
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
|
||||
"version": "1.2.6",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
|
||||
"integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q=="
|
||||
},
|
||||
"minipass": {
|
||||
"version": "2.2.4",
|
||||
|
@ -15,7 +15,7 @@
|
||||
"@microsoft/sp-lodash-subset": "~1.4.1",
|
||||
"@microsoft/sp-office-ui-fabric-core": "~1.4.1",
|
||||
"@types/webpack-env": ">=1.12.1 <1.14.0",
|
||||
"minimist": ">=1.2.3",
|
||||
"minimist": ">=1.2.6",
|
||||
"acorn": ">=5.7.4",
|
||||
"kind-of": ">=6.0.3",
|
||||
"cryptiles": ">=4.1.2",
|
||||
|
6
samples/react-flow-button/package-lock.json
generated
6
samples/react-flow-button/package-lock.json
generated
@ -21113,9 +21113,9 @@
|
||||
}
|
||||
},
|
||||
"url-parse": {
|
||||
"version": "1.5.8",
|
||||
"resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.8.tgz",
|
||||
"integrity": "sha512-9JZ5zDrn9wJoOy/t+rH00HHejbU8dq9VsOYVu272TYDrCiyVAgHKUSpPh3ruZIpv8PMVR+NXLZvfRPJv8xAcQw==",
|
||||
"version": "1.5.10",
|
||||
"resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz",
|
||||
"integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"querystringify": "^2.1.1",
|
||||
|
@ -22750,9 +22750,9 @@
|
||||
}
|
||||
},
|
||||
"url-parse": {
|
||||
"version": "1.5.8",
|
||||
"resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.8.tgz",
|
||||
"integrity": "sha512-9JZ5zDrn9wJoOy/t+rH00HHejbU8dq9VsOYVu272TYDrCiyVAgHKUSpPh3ruZIpv8PMVR+NXLZvfRPJv8xAcQw==",
|
||||
"version": "1.5.10",
|
||||
"resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz",
|
||||
"integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"querystringify": "^2.1.1",
|
||||
|
@ -0,0 +1,39 @@
|
||||
// For more information on how to run this SPFx project in a VS Code Remote Container, please visit https://aka.ms/spfx-devcontainer
|
||||
{
|
||||
"name": "SPFx 1.14.0",
|
||||
"image": "docker.io/m365pnp/spfx:1.14.0",
|
||||
// Set *default* container specific settings.json values on container create.
|
||||
"settings": {},
|
||||
// Add the IDs of extensions you want installed when the container is created.
|
||||
"extensions": [
|
||||
"editorconfig.editorconfig",
|
||||
"dbaeumer.vscode-eslint"
|
||||
],
|
||||
// Use 'forwardPorts' to make a list of ports inside the container available locally.
|
||||
"forwardPorts": [
|
||||
4321,
|
||||
35729
|
||||
],
|
||||
"portsAttributes": {
|
||||
"4321": {
|
||||
"protocol": "https",
|
||||
"label": "Manifest",
|
||||
"onAutoForward": "silent",
|
||||
"requireLocalPort": true
|
||||
},
|
||||
// Not needed for SPFx>= 1.12.1
|
||||
// "5432": {
|
||||
// "protocol": "https",
|
||||
// "label": "Workbench",
|
||||
// "onAutoForward": "silent"
|
||||
// },
|
||||
"35729": {
|
||||
"protocol": "https",
|
||||
"label": "LiveReload",
|
||||
"onAutoForward": "silent",
|
||||
"requireLocalPort": true
|
||||
}
|
||||
},
|
||||
"postCreateCommand": "bash .devcontainer/spfx-startup.sh",
|
||||
"remoteUser": "node"
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
echo
|
||||
echo -e "\e[1;94mInstalling Node dependencies\e[0m"
|
||||
npm install
|
||||
|
||||
## commands to create dev certificate and copy it to the root folder of the project
|
||||
echo
|
||||
echo -e "\e[1;94mGenerating dev certificate\e[0m"
|
||||
gulp trust-dev-cert
|
||||
|
||||
# Convert the generated PEM certificate to a CER certificate
|
||||
openssl x509 -inform PEM -in ~/.rushstack/rushstack-serve.pem -outform DER -out ./spfx-dev-cert.cer
|
||||
|
||||
# Copy the PEM ecrtificate for non-Windows hosts
|
||||
cp ~/.rushstack/rushstack-serve.pem ./spfx-dev-cert.pem
|
||||
|
||||
## add *.cer to .gitignore to prevent certificates from being saved in repo
|
||||
if ! grep -Fxq '*.cer' ./.gitignore
|
||||
then
|
||||
echo "# .CER Certificates" >> .gitignore
|
||||
echo "*.cer" >> .gitignore
|
||||
fi
|
||||
|
||||
## add *.pem to .gitignore to prevent certificates from being saved in repo
|
||||
if ! grep -Fxq '*.pem' ./.gitignore
|
||||
then
|
||||
echo "# .PEM Certificates" >> .gitignore
|
||||
echo "*.pem" >> .gitignore
|
||||
fi
|
||||
|
||||
echo
|
||||
echo -e "\e[1;92mReady!\e[0m"
|
||||
|
||||
echo -e "\n\e[1;94m**********\nOptional: if you plan on using gulp serve, don't forget to add the container certificate to your local machine. Please visit https://aka.ms/spfx-devcontainer for more information\n**********"
|
@ -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
|
@ -9,6 +9,7 @@ node_modules
|
||||
# Build generated files
|
||||
dist
|
||||
lib
|
||||
release
|
||||
solution
|
||||
temp
|
||||
*.sppkg
|
||||
@ -30,4 +31,7 @@ obj
|
||||
|
||||
# Styles Generated Code
|
||||
*.scss.ts
|
||||
*.scss.d.ts
|
||||
*.scss.d.ts# .CER Certificates
|
||||
*.cer
|
||||
# .PEM Certificates
|
||||
*.pem
|
||||
|
16
samples/react-graph-cascading-managed-metadata/.npmignore
Normal file
16
samples/react-graph-cascading-managed-metadata/.npmignore
Normal file
@ -0,0 +1,16 @@
|
||||
!dist
|
||||
config
|
||||
|
||||
gulpfile.js
|
||||
|
||||
release
|
||||
src
|
||||
temp
|
||||
|
||||
tsconfig.json
|
||||
tslint.json
|
||||
|
||||
*.log
|
||||
|
||||
.yo-rc.json
|
||||
.vscode
|
@ -2,7 +2,7 @@
|
||||
"@microsoft/generator-sharepoint": {
|
||||
"isCreatingSolution": true,
|
||||
"environment": "spo",
|
||||
"version": "1.9.1",
|
||||
"version": "1.14.0",
|
||||
"libraryName": "react-graph-cascading-managed-metadata",
|
||||
"libraryId": "cdc626ca-e9a7-4d1d-bded-a574bc5e61d0",
|
||||
"packageManager": "npm",
|
||||
|
@ -8,19 +8,14 @@ This web part shows how to use the Microsoft Graph APIs (beta) for Taxonomy to g
|
||||
|
||||

|
||||
|
||||
### Termstore
|
||||
|
||||

|
||||
|
||||
## Compatibility
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
-Incompatible-red.svg "SharePoint Server 2016 Feature Pack 2 requires SPFx 1.1")
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
@ -31,16 +26,18 @@ This web part shows how to use the Microsoft Graph APIs (beta) for Taxonomy to g
|
||||
|
||||
## Pre-requisites
|
||||
|
||||
* Set up the termset structure as shown in the image above.
|
||||
* Set up the termset structure as shown in the image below - .
|
||||
* To the termset, add a custom property called `UsedForShowingMaps` and set it's value to `true` as shown in the image below
|
||||

|
||||
* For the cities, get the required latitude and longitude.
|
||||
* Set the description of the city term as `latitude;longitude` (as highlighted for the term `London` in the image above).
|
||||
|
||||
* Add 2 custom properties for the city terms `latitude` and `longitude` (as highlighted for the term `London` in the image below).
|
||||

|
||||
|
||||
## Solution
|
||||
|
||||
Solution|Author(s)
|
||||
--------|---------
|
||||
react-graph-cascading-managed-metadata| Anoop Tatti ([anoopt](https://github.com/anoopt), [@anooptells](https://twitter.com/anooptells))
|
||||
react-graph-cascading-managed-metadata| Anoop Tatti ([anoopt](https://github.com/anoopt), ([https://linktr.ee/anoopt](https://linktr.ee/anoopt))
|
||||
|
||||
## Version history
|
||||
|
||||
@ -48,6 +45,7 @@ Version|Date|Comments
|
||||
-------|----|--------
|
||||
1.0.0|Aug 24, 2020|Initial release
|
||||
1.0.1|Sep 03, 2020|Error handling and logging improvements
|
||||
2.0.0|Mar 04, 2022|Updated to SPFx 1.14, used term `custom properties` to get co-ordinates (as Graph API provides that capability now), usage of `PropertyFieldGuid` and several other improvements
|
||||
|
||||
## Minimal Path to Awesome
|
||||
|
||||
@ -55,14 +53,17 @@ Version|Date|Comments
|
||||
* in the command line run:
|
||||
* `npm install`
|
||||
* `gulp serve`
|
||||
* Make sure you have completed the [pre-requisites](#Pre-requisites)
|
||||
* Add the web part to the workbench page of a site
|
||||
* Edit the web part and add the termset id in the properties
|
||||
|
||||
> This sample can also be opened with [VS Code Remote Development](https://code.visualstudio.com/docs/remote/remote-overview). Visit https://aka.ms/spfx-devcontainer for further instructions.
|
||||
> This sample can also be opened with [VS Code Remote Development](https://code.visualstudio.com/docs/remote/remote-overview). Visit <https://aka.ms/spfx-devcontainer> for further instructions.
|
||||
|
||||
## Features
|
||||
|
||||
This sample illustrates the following concepts on top of the SharePoint Framework:
|
||||
|
||||
* Get data terms using Microsoft Graph API (beta).
|
||||
* Get termset, terms and their custom properties using Microsoft Graph API (beta).
|
||||
* React Hooks
|
||||
* Using async / await for the async calls
|
||||
* Caching the data in session storage
|
||||
@ -72,12 +73,15 @@ This sample illustrates the following concepts on top of the SharePoint Framewor
|
||||
### Enhancements
|
||||
|
||||
* Currently, this web part supports 2-level cascading. So there is scope to enhance this such that it supports more levels of cascading dynamically.
|
||||
* Currently, this web part reads latitude and longitude from description of the city terms. If there is a way of getting these from the custom properties of the city terms, then that needs to be implemented.
|
||||
|
||||
## Video
|
||||
|
||||
[](https://www.youtube.com/watch?v=lk47ijo_H6Y "Cascading managed metadata using Microsoft Graph and SharePoint Framework")
|
||||
|
||||
## Need to show more details?
|
||||
|
||||
An Adaptive Card Extension (ACE) which performs similar operations and provides more data like the local time of the office, weather data of the office location and address of the office location along with it's map can be found in the `Office locations` sample of [pnp/sp-dev-fx-aces repostory](https://github.com/pnp/sp-dev-fx-aces/tree/main/samples/ImageCard-OfficeLocations).
|
||||
|
||||
## 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.
|
||||
@ -90,11 +94,8 @@ For questions regarding this sample, [create a new question](https://github.com/
|
||||
|
||||
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%3Aenhancement%2Csample%3A%20react-graph-cascading-managed-metadata&template=question.yml&sample=react-graph-cascading-managed-metadata&authors=@anoopt&title=react-graph-cascading-managed-metadata%20-%20).
|
||||
|
||||
|
||||
|
||||
## 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.**
|
||||
|
||||
|
||||
<img src="https://pnptelemetry.azurewebsites.net/sp-dev-fx-webparts/samples/react-graph-cascading-managed-metadata" />
|
||||
|
@ -9,7 +9,7 @@
|
||||
"Shows how to use the Microsoft Graph APIs (beta) for Taxonomy to get the data."
|
||||
],
|
||||
"creationDateTime": "2020-09-02",
|
||||
"updateDateTime": "2020-09-02",
|
||||
"updateDateTime": "2022-03-02",
|
||||
"products": [
|
||||
"SharePoint"
|
||||
],
|
||||
@ -20,7 +20,7 @@
|
||||
},
|
||||
{
|
||||
"key": "SPFX-VERSION",
|
||||
"value": "1.11.0"
|
||||
"value": "1.14.0"
|
||||
}
|
||||
],
|
||||
"thumbnails": [
|
||||
|
Binary file not shown.
After Width: | Height: | Size: 47 KiB |
Binary file not shown.
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 33 KiB |
@ -14,6 +14,7 @@
|
||||
"externals": {},
|
||||
"localizedResources": {
|
||||
"CascadingManagedMetadataWebPartStrings": "lib/webparts/cascadingManagedMetadata/loc/{locale}.js",
|
||||
"ControlStrings": "node_modules/@pnp/spfx-controls-react/lib/loc/{locale}.js"
|
||||
"ControlStrings": "node_modules/@pnp/spfx-controls-react/lib/loc/{locale}.js",
|
||||
"PropertyControlStrings": "node_modules/@pnp/spfx-property-controls/lib/loc/{locale}.js"
|
||||
}
|
||||
}
|
@ -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-graph-cascading-managed-metadata",
|
||||
"accessKey": "<!-- ACCESS KEY -->"
|
||||
|
@ -2,6 +2,21 @@
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/package-solution.schema.json",
|
||||
"solution": {
|
||||
"name": "react-graph-cascading-managed-metadata-client-side-solution",
|
||||
"developer": {
|
||||
"name": "",
|
||||
"privacyUrl": "",
|
||||
"termsOfUseUrl": "",
|
||||
"websiteUrl": "",
|
||||
"mpnId": "Undefined-1.14.0"
|
||||
},
|
||||
"metadata": {
|
||||
"shortDescription": {
|
||||
"default": "react-graph-cascading-managed-metadata description"
|
||||
},
|
||||
"longDescription": {
|
||||
"default": "react-graph-cascading-managed-metadata description"
|
||||
}
|
||||
},
|
||||
"id": "cdc626ca-e9a7-4d1d-bded-a574bc5e61d0",
|
||||
"version": "1.0.0.0",
|
||||
"includeClientSideAssets": true,
|
||||
@ -11,4 +26,4 @@
|
||||
"paths": {
|
||||
"zippedPackage": "solution/react-graph-cascading-managed-metadata.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"
|
||||
}
|
||||
|
@ -0,0 +1,9 @@
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/s-KaiNet/spfx-fast-serve/master/schema/config.latest.schema.json",
|
||||
"cli": {
|
||||
"isLibraryComponent": false
|
||||
},
|
||||
"serve": {
|
||||
"open": false
|
||||
}
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* User webpack settings file. You can add your own settings here.
|
||||
* Changes from this file will be merged into the base webpack configuration file.
|
||||
* This file will not be overwritten by the subsequent spfx-fast-serve calls.
|
||||
*/
|
||||
|
||||
// you can add your project related webpack configuration here, it will be merged using webpack-merge module
|
||||
// i.e. plugins: [new webpack.Plugin()]
|
||||
const webpackConfig = {
|
||||
|
||||
}
|
||||
|
||||
// for even more fine-grained control, you can apply custom webpack settings using below function
|
||||
const transformConfig = function (initialWebpackConfig) {
|
||||
// transform the initial webpack config here, i.e.
|
||||
// initialWebpackConfig.plugins.push(new webpack.Plugin()); etc.
|
||||
|
||||
return initialWebpackConfig;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
webpackConfig,
|
||||
transformConfig
|
||||
}
|
@ -1,36 +1,21 @@
|
||||
'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.`);
|
||||
|
||||
const argv = build.rig.getYargs().argv;
|
||||
const useCustomServe = argv['custom-serve'];
|
||||
const fs = require("fs");
|
||||
const workbenchApi = require("@microsoft/sp-webpart-workbench/lib/api");
|
||||
var getTasks = build.rig.getTasks;
|
||||
build.rig.getTasks = function () {
|
||||
var result = getTasks.call(build.rig);
|
||||
|
||||
if (useCustomServe) {
|
||||
build.tslintCmd.enabled = false;
|
||||
|
||||
const ensureWorkbenchSubtask = build.subTask('ensure-workbench-task', function (gulp, buildOptions, done) {
|
||||
this.log('Creating workbench.html file...');
|
||||
try {
|
||||
workbenchApi.default["/workbench"]();
|
||||
} catch (e) { }
|
||||
result.set('serve', result.get('serve-deprecated'));
|
||||
|
||||
done();
|
||||
});
|
||||
return result;
|
||||
};
|
||||
|
||||
build.rig.addPostBuildTask(build.task('ensure-workbench', ensureWorkbenchSubtask));
|
||||
|
||||
build.configureWebpack.mergeConfig({
|
||||
additionalConfiguration: (generatedConfiguration) => {
|
||||
fs.writeFileSync("./temp/_webpack_config.json", JSON.stringify(generatedConfiguration, null, 2));
|
||||
return generatedConfiguration;
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
/* fast-serve */
|
||||
const { addFastServe } = require("spfx-fast-serve-helpers");
|
||||
addFastServe(build);
|
||||
/* end of fast-serve */
|
||||
|
||||
build.initialize(require('gulp'));
|
||||
|
||||
|
25415
samples/react-graph-cascading-managed-metadata/package-lock.json
generated
25415
samples/react-graph-cascading-managed-metadata/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -3,51 +3,34 @@
|
||||
"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",
|
||||
"serve": "cross-env NODE_OPTIONS=--max_old_space_size=4096 gulp bundle --custom-serve && cross-env NODE_OPTIONS=--max_old_space_size=4096 webpack-dev-server --mode development --config ./webpack.js --env.env=dev"
|
||||
"serve": "gulp bundle --custom-serve --max_old_space_size=4096 && fast-serve"
|
||||
},
|
||||
"dependencies": {
|
||||
"@microsoft/sp-core-library": "1.11.0",
|
||||
"@microsoft/sp-lodash-subset": "1.11.0",
|
||||
"@microsoft/sp-office-ui-fabric-core": "1.11.0",
|
||||
"@microsoft/sp-property-pane": "1.11.0",
|
||||
"@microsoft/sp-webpart-base": "1.11.0",
|
||||
"@pnp/spfx-controls-react": "^1.20.0-beta.52e4e9f",
|
||||
"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.14.0",
|
||||
"@microsoft/sp-lodash-subset": "1.14.0",
|
||||
"@microsoft/sp-office-ui-fabric-core": "1.14.0",
|
||||
"@microsoft/sp-property-pane": "1.14.0",
|
||||
"@microsoft/sp-webpart-base": "1.14.0",
|
||||
"@pnp/spfx-controls-react": "3.5.0",
|
||||
"@pnp/spfx-property-controls": "3.5.0",
|
||||
"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.16",
|
||||
"@microsoft/rush-stack-compiler-3.3": "0.3.5",
|
||||
"@microsoft/sp-build-web": "1.11.0",
|
||||
"@microsoft/sp-module-interfaces": "1.11.0",
|
||||
"@microsoft/sp-tslint-rules": "1.11.0",
|
||||
"@microsoft/sp-webpart-workbench": "1.11.0",
|
||||
"@types/chai": "3.4.34",
|
||||
"@types/mocha": "2.2.38",
|
||||
"@microsoft/rush-stack-compiler-3.9": "0.4.47",
|
||||
"@microsoft/sp-build-web": "1.14.0",
|
||||
"@microsoft/sp-module-interfaces": "1.14.0",
|
||||
"@microsoft/sp-tslint-rules": "1.14.0",
|
||||
"@types/react": "16.9.51",
|
||||
"@types/react-dom": "16.9.8",
|
||||
"@types/webpack-env": "1.13.1",
|
||||
"ajv": "~5.2.2",
|
||||
"cross-env": "7.0.2",
|
||||
"css-loader": "3.4.2",
|
||||
"css-modules-typescript-loader": "4.0.0",
|
||||
"del": "5.1.0",
|
||||
"fork-ts-checker-webpack-plugin": "4.1.0",
|
||||
"gulp": "~3.9.1",
|
||||
"node-sass": "4.13.1",
|
||||
"sass-loader": "8.0.2",
|
||||
"style-loader": "1.1.3",
|
||||
"ts-loader": "6.2.1",
|
||||
"webpack": "4.42.0",
|
||||
"webpack-cli": "3.3.11",
|
||||
"webpack-dev-server": "3.10.3"
|
||||
"gulp": "~4.0.2",
|
||||
"spfx-fast-serve-helpers": "~1.14.0"
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,9 @@
|
||||
import * as React from 'react';
|
||||
import * as ReactDom from 'react-dom';
|
||||
import { Version, DisplayMode, Guid } from '@microsoft/sp-core-library';
|
||||
import {
|
||||
BaseClientSideWebPart,
|
||||
IPropertyPaneConfiguration,
|
||||
PropertyPaneTextField
|
||||
} from '@microsoft/sp-webpart-base';
|
||||
|
||||
import { Version, DisplayMode } from '@microsoft/sp-core-library';
|
||||
import { BaseClientSideWebPart } from "@microsoft/sp-webpart-base";
|
||||
import { IPropertyPaneConfiguration } from "@microsoft/sp-property-pane";
|
||||
import { PropertyFieldGuid } from '@pnp/spfx-property-controls/lib/PropertyFieldGuid';
|
||||
import * as strings from 'CascadingManagedMetadataWebPartStrings';
|
||||
import CascadingManagedMetadata from './components/CascadingManagedMetadata';
|
||||
import { MSGraph } from './services/MSGraph';
|
||||
@ -19,8 +16,12 @@ export default class CascadingManagedMetadataWebPart extends BaseClientSideWebPa
|
||||
|
||||
private _placeholder = null;
|
||||
|
||||
public async render(): Promise<void> {
|
||||
protected async onInit(): Promise<void> {
|
||||
await MSGraph.Init(this.context);
|
||||
return super.onInit();
|
||||
}
|
||||
|
||||
public async render(): Promise<void> {
|
||||
let renderElement = null;
|
||||
if (this.properties.termSetId) {
|
||||
renderElement = React.createElement(
|
||||
@ -68,18 +69,6 @@ export default class CascadingManagedMetadataWebPart extends BaseClientSideWebPa
|
||||
return Version.parse('1.0');
|
||||
}
|
||||
|
||||
private validateTermSetId(value: string): string {
|
||||
if (value === null ||
|
||||
value.trim().length === 0) {
|
||||
return 'Provide a term set Id.';
|
||||
}
|
||||
|
||||
if (!Guid.isValid(value.trim())) {
|
||||
return 'Term set Id must be a valid GUID.';
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration {
|
||||
return {
|
||||
@ -92,9 +81,11 @@ export default class CascadingManagedMetadataWebPart extends BaseClientSideWebPa
|
||||
{
|
||||
groupName: strings.BasicGroupName,
|
||||
groupFields: [
|
||||
PropertyPaneTextField('termSetId', {
|
||||
PropertyFieldGuid('termSetId', {
|
||||
key: 'termSetId',
|
||||
label: strings.TermSetIdFieldLabel,
|
||||
onGetErrorMessage: this.validateTermSetId.bind(this)
|
||||
value: this.properties.termSetId,
|
||||
errorMessage: "Term set Id must be a valid GUID"
|
||||
})
|
||||
]
|
||||
}
|
||||
|
@ -1,20 +1,20 @@
|
||||
import * as React from 'react';
|
||||
import styles from './CascadingManagedMetadata.module.scss';
|
||||
import { ICascadingManagedMetadataProps } from './ICascadingManagedMetadataProps';
|
||||
import { MSGraph } from '../services/MSGraph';
|
||||
import { ITerms } from '../../interfaces';
|
||||
import { ICMMDDropdownOption, IProperty, ITerms } from '../../interfaces';
|
||||
|
||||
import { Dropdown, IDropdownOption } from 'office-ui-fabric-react/lib/Dropdown';
|
||||
import { MessageBar, MessageBarType } from 'office-ui-fabric-react/lib/MessageBar';
|
||||
import { Map, ICoordinates } from "@pnp/spfx-controls-react/lib/Map";
|
||||
import { MMDService } from '../services/MMDService';
|
||||
import { find, isEmpty } from '@microsoft/sp-lodash-subset';
|
||||
|
||||
|
||||
const CascadingManagedMetadata: React.SFC<ICascadingManagedMetadataProps> = (props) => {
|
||||
|
||||
const [countriesList, setCountriesList] = React.useState<IDropdownOption[]>([]);
|
||||
const [citiesList, setCitiesList] = React.useState<IDropdownOption[]>([]);
|
||||
const [selectedCityCoordinates, setSelectedCityCoordinates] = React.useState<string>(null);
|
||||
const [citiesList, setCitiesList] = React.useState<ICMMDDropdownOption[]>([]);
|
||||
const [selectedCityKey, setselectedCityKey] = React.useState<string>(null);
|
||||
const [selectedCity, setSelectedCity] = React.useState<string>(null);
|
||||
const [showMap, setShowMap] = React.useState<boolean>(false);
|
||||
const [coordinates, setCoordinates] = React.useState<ICoordinates>({ latitude: null, longitude: null });
|
||||
@ -26,22 +26,34 @@ const CascadingManagedMetadata: React.SFC<ICascadingManagedMetadataProps> = (pro
|
||||
|
||||
const LOG_SOURCE: string = "Cascading MMD -";
|
||||
|
||||
React.useEffect(() => {
|
||||
_getCountries().then(countries => {
|
||||
if (countries) {
|
||||
const options: IDropdownOption[] = countries.value.map(c => ({ key: c.id, text: c.labels[0].name }));
|
||||
setCountriesList(options);
|
||||
} else {
|
||||
setCountriesList([]);
|
||||
clearData();
|
||||
//* Check if the term set has a property called UsedForShowingMaps
|
||||
const _checkIfTermsetIsUsedForShowingMaps = async (): Promise<boolean> => {
|
||||
try {
|
||||
const termsetData = await MSGraph.Call('get', `/termStore/sets/${props.termSetId}`, "beta", {}, ["properties"]);
|
||||
const termsetProperties: IProperty[] = termsetData.properties;
|
||||
console.debug("%s Retrieved termset properties. %o", LOG_SOURCE, termsetProperties);
|
||||
|
||||
if (isEmpty(termsetProperties)) {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}, [props.termSetId]); //* Run this also when the property termSetId changes
|
||||
return find(termsetProperties, (p: IProperty) => p.key === "UsedForShowingMaps")?.value === "true";
|
||||
|
||||
}
|
||||
catch (error) {
|
||||
console.error("%s Error retrieving termset properties. Details - %o", LOG_SOURCE, error);
|
||||
setMessageBarStatus({
|
||||
type: MessageBarType.error,
|
||||
message: <span>Error retrieving termset properties. Please contact admin.</span>,
|
||||
show: true
|
||||
});
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
//* Get the country terms i.e. level 1 children using Graph
|
||||
const _getCountries = async (): Promise<ITerms> => {
|
||||
try {
|
||||
let countries: ITerms = await MSGraph.Get(`/termStore/sets/${props.termSetId}/children`, "beta");
|
||||
let countries: ITerms = await MSGraph.Call('get', `/termStore/sets/${props.termSetId}/children`, "beta");
|
||||
setMessageBarStatus(state => ({ ...state, show: false }));
|
||||
console.debug("%s Retrieved countries. %o", LOG_SOURCE, countries);
|
||||
return countries;
|
||||
@ -58,51 +70,52 @@ const CascadingManagedMetadata: React.SFC<ICascadingManagedMetadataProps> = (pro
|
||||
};
|
||||
|
||||
//* Get the city terms under a country i.e. level 2 children using Graph
|
||||
const _onCountryChange = (event: React.FormEvent<HTMLDivElement>, item: IDropdownOption): void => {
|
||||
clearData();
|
||||
let countryTermId: string = item.key.toString();
|
||||
const _onCountryChange = async (event: React.FormEvent<HTMLDivElement>, item: IDropdownOption): Promise<void> => {
|
||||
|
||||
MMDService.GetTermsAsDropdownOptions(`/termStore/sets/${props.termSetId}/terms/${countryTermId}/children`, countryTermId, true)
|
||||
.then(options => {
|
||||
setCitiesList(options);
|
||||
//setShowMap(false);
|
||||
console.debug("%s Retrieved cities. %o", LOG_SOURCE, options);
|
||||
setMessageBarStatus({
|
||||
type: MessageBarType.warning,
|
||||
message: options.length > 0 ?
|
||||
<span>To see the map, please select a city. </span> :
|
||||
<span> No city terms in the selected country.</span>,
|
||||
show: true
|
||||
});
|
||||
})
|
||||
.catch(error => {
|
||||
console.error("%s Error retrieving cities. Details - %o", LOG_SOURCE, error);
|
||||
setMessageBarStatus({
|
||||
type: MessageBarType.error,
|
||||
message: <span>Error in retrieving cities. Please contact admin.</span>,
|
||||
show: true
|
||||
});
|
||||
setCitiesList([]);
|
||||
try {
|
||||
clearData();
|
||||
let countryTermId: string = item.key.toString();
|
||||
|
||||
let cities: ICMMDDropdownOption[] = await MMDService
|
||||
.GetTermsAsDropdownOptions(
|
||||
`/termStore/sets/${props.termSetId}/terms/${countryTermId}/children`,
|
||||
["id", "labels", "properties"],
|
||||
countryTermId,
|
||||
true);
|
||||
setCitiesList(cities);
|
||||
setMessageBarStatus({
|
||||
type: MessageBarType.warning,
|
||||
message: cities.length > 0 ?
|
||||
<span>To see the map, please select a city. </span> :
|
||||
<span> No city terms in the selected country.</span>,
|
||||
show: true
|
||||
});
|
||||
console.debug("%s Retrieved cities. %o", LOG_SOURCE, cities);
|
||||
}
|
||||
catch (error) {
|
||||
console.error("%s Error retrieving cities. Details - %o", LOG_SOURCE, error);
|
||||
setMessageBarStatus({
|
||||
type: MessageBarType.error,
|
||||
message: <span>Error in retrieving cities. Please contact admin.</span>,
|
||||
show: true
|
||||
});
|
||||
setCitiesList([]);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
//* Extract co-ordinates from key of the dropdown option
|
||||
//* The key will contain the description of the term
|
||||
//* The description of the term will be of the format latitude;longitude
|
||||
const _onCityChange = (event: React.FormEvent<HTMLDivElement>, item: IDropdownOption): void => {
|
||||
setSelectedCity(item.text);
|
||||
setSelectedCityCoordinates(item.key.toString());
|
||||
const [lat, long] = item.key.toString().split(';');
|
||||
const coordinates: ICoordinates = {
|
||||
latitude: isNaN(Number(lat)) ? null : Number(lat),
|
||||
longitude: isNaN(Number(long)) ? null : Number(long)
|
||||
};
|
||||
setCoordinates(coordinates);
|
||||
|
||||
console.debug("%s Retrieved coordinates. %o", LOG_SOURCE, coordinates);
|
||||
const _onCityChange = (event: React.FormEvent<HTMLDivElement>, item: ICMMDDropdownOption): void => {
|
||||
|
||||
if (coordinates.latitude && coordinates.longitude) {
|
||||
const { text, key, data } = item;
|
||||
|
||||
setSelectedCity(text);
|
||||
setselectedCityKey(key.toString());
|
||||
setCoordinates(data);
|
||||
|
||||
console.debug("%s Retrieved coordinates. %o", LOG_SOURCE, data);
|
||||
|
||||
if (data.latitude && data.longitude) {
|
||||
setShowMap(true);
|
||||
setMessageBarStatus(state => ({ ...state, show: false }));
|
||||
} else {
|
||||
@ -118,11 +131,59 @@ const CascadingManagedMetadata: React.SFC<ICascadingManagedMetadataProps> = (pro
|
||||
//* Clear the data related to cities and maps
|
||||
const clearData = () => {
|
||||
setCoordinates({ latitude: null, longitude: null });
|
||||
setSelectedCityCoordinates(null);
|
||||
setselectedCityKey(null);
|
||||
setSelectedCity(null);
|
||||
setCitiesList([]);
|
||||
setShowMap(false);
|
||||
}
|
||||
};
|
||||
|
||||
const _start = async (): Promise<void> => {
|
||||
|
||||
let isTermsetUsedForShowingMaps: boolean = await _checkIfTermsetIsUsedForShowingMaps();
|
||||
|
||||
if(isTermsetUsedForShowingMaps === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isTermsetUsedForShowingMaps) {
|
||||
setCountriesList([]);
|
||||
clearData();
|
||||
setMessageBarStatus({
|
||||
type: MessageBarType.warning,
|
||||
message: <span>The selected term set is not used for showing maps.</span>,
|
||||
show: true
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
let countries: ITerms = await _getCountries();
|
||||
|
||||
if(countries === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isEmpty(countries.value)) {
|
||||
setCountriesList([]);
|
||||
clearData();
|
||||
setMessageBarStatus({
|
||||
type: MessageBarType.warning,
|
||||
message: <span>No country terms in the selected termset. Please contact admin.</span>,
|
||||
show: true
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Renamed to avoid shadowed variables
|
||||
let localCountriesList: IDropdownOption[] = countries.value.map(c => ({ key: c.id, text: c.labels[0].name }));
|
||||
setCountriesList(localCountriesList);
|
||||
|
||||
};
|
||||
|
||||
React.useEffect(() => {
|
||||
_start();
|
||||
}, [props.termSetId]); //* Run this also when the property termSetId changes
|
||||
|
||||
|
||||
|
||||
return (
|
||||
<div>
|
||||
@ -136,7 +197,7 @@ const CascadingManagedMetadata: React.SFC<ICascadingManagedMetadataProps> = (pro
|
||||
|
||||
<Dropdown
|
||||
label="City"
|
||||
selectedKey={selectedCityCoordinates}
|
||||
selectedKey={selectedCityKey}
|
||||
placeHolder="Select a city"
|
||||
options={citiesList}
|
||||
onChange={_onCityChange}
|
||||
|
@ -1,47 +1,44 @@
|
||||
import { ITerms, IOption } from "../../interfaces";
|
||||
import { ITerms, ICMMDDropdownOption } from "../../interfaces";
|
||||
import { MSGraph } from "./MSGraph";
|
||||
import { IDropdownOption } from "office-ui-fabric-react/lib/Dropdown";
|
||||
import { find } from '@microsoft/sp-lodash-subset';
|
||||
|
||||
export class MMDService {
|
||||
|
||||
private static _sessionStorageKey: string = "CMMD_Options";
|
||||
private static _logSource: string = "Cascading MMD Service -";
|
||||
|
||||
public static async GetTermsAsDropdownOptions(apiUrl: string, parent: string, tryFromCache: boolean): Promise<IDropdownOption[]> {
|
||||
|
||||
let options: IDropdownOption[] = [];
|
||||
public static async GetTermsAsDropdownOptions(apiUrl: string, selectProperties: string[], parent: string, tryFromCache: boolean): Promise<ICMMDDropdownOption[]> {
|
||||
if (tryFromCache) {
|
||||
let optionsFromCache: IOption[] = this._fetchFromSessionStorge();
|
||||
let optionsFromCache: ICMMDDropdownOption[] = this._fetchFromSessionStorge();
|
||||
|
||||
if (optionsFromCache.length) {
|
||||
let requiredOptionsFromCache = optionsFromCache.filter(o => o.parent == parent);
|
||||
if (requiredOptionsFromCache.length) {
|
||||
options = requiredOptionsFromCache.map(r => ({ key: r.key, text: r.text }));
|
||||
return options;
|
||||
return requiredOptionsFromCache;
|
||||
}
|
||||
}
|
||||
}
|
||||
//Get data using Graph
|
||||
return await this._getTermsAsDropdownOptionsUsingGraph(apiUrl, parent);
|
||||
return await this._getTermsAsDropdownOptionsUsingGraph(apiUrl, selectProperties, parent);
|
||||
}
|
||||
|
||||
private static async _getTermsAsDropdownOptionsUsingGraph(apiUrl: string, parent: string): Promise<IDropdownOption[]> {
|
||||
private static async _getTermsAsDropdownOptionsUsingGraph(apiUrl: string, selectProperties: string[], parent: string): Promise<ICMMDDropdownOption[]> {
|
||||
try {
|
||||
let terms: ITerms = await MSGraph.Get(apiUrl, "beta");
|
||||
let terms: ITerms = await MSGraph.Call("get", apiUrl, "beta", {}, selectProperties);
|
||||
if (terms.value) {
|
||||
//* Set key as description of the term
|
||||
//* Description will be of the format latitude;longitude
|
||||
//* This will be used to render maps
|
||||
const options: IDropdownOption[] = terms.value.map(t => ({
|
||||
key: t.descriptions[0] ? t.descriptions[0].description : t.id,
|
||||
text: t.labels[0].name
|
||||
}));
|
||||
let optionsToStoreInCache: IOption[] = options.map(o => ({
|
||||
key: o.key.toString(),
|
||||
text: o.text,
|
||||
const options: ICMMDDropdownOption[] = terms.value.map(t => ({
|
||||
key: t.id,
|
||||
text: t.labels[0].name,
|
||||
data: {
|
||||
latitude: Number(find(t.properties, p => p.key === "latitude")?.value) ?? null,
|
||||
longitude: Number(find(t.properties, p => p.key === "longitude")?.value) ?? null,
|
||||
},
|
||||
parent
|
||||
}));
|
||||
let optionsFromCache: IOption[] = this._fetchFromSessionStorge();
|
||||
optionsToStoreInCache = [...optionsFromCache, ...optionsToStoreInCache];
|
||||
|
||||
let optionsFromCache: ICMMDDropdownOption[] = this._fetchFromSessionStorge();
|
||||
let optionsToStoreInCache: ICMMDDropdownOption[] = [...optionsFromCache, ...options];
|
||||
window.sessionStorage.setItem(this._sessionStorageKey, JSON.stringify(optionsToStoreInCache));
|
||||
console.debug("%s Data added in cache.", this._logSource);
|
||||
return options;
|
||||
@ -55,8 +52,8 @@ export class MMDService {
|
||||
|
||||
}
|
||||
|
||||
private static _fetchFromSessionStorge(): IOption[] {
|
||||
let result: IOption[] = [];
|
||||
private static _fetchFromSessionStorge(): ICMMDDropdownOption[] {
|
||||
let result: ICMMDDropdownOption[] = [];
|
||||
let stringResult: string = window.sessionStorage.getItem(this._sessionStorageKey);
|
||||
if (stringResult) {
|
||||
try {
|
||||
|
@ -1,3 +1,5 @@
|
||||
//* Helper wrapper for calling Graph
|
||||
//* based on https://gist.github.com/wobba/37416d3107b85675d896105554b3df28
|
||||
//* Thank you Mikael Svenson
|
||||
|
||||
import { WebPartContext } from '@microsoft/sp-webpart-base';
|
||||
@ -6,85 +8,38 @@ import { MSGraphClient } from '@microsoft/sp-http';
|
||||
|
||||
export class MSGraph {
|
||||
private static _graphClient: MSGraphClient;
|
||||
|
||||
public static async Init(context: WebPartContext) {
|
||||
this._graphClient = await context.msGraphClientFactory.getClient();
|
||||
}
|
||||
|
||||
public static async Get(apiUrl: string, version: string = "v1.0", selectProperties?: string[], expandProperties?: string[], filter?: string): Promise<any> {
|
||||
public static async Call(
|
||||
method: "get" | "post" | "patch" | "delete",
|
||||
apiUrl: string,
|
||||
version: "v1.0" | "beta",
|
||||
content?: any,
|
||||
selectProperties?: string[],
|
||||
expandProperties?: string[],
|
||||
filter?: string,
|
||||
count?: boolean
|
||||
): Promise<any> {
|
||||
|
||||
var p = new Promise<string>(async (resolve, reject) => {
|
||||
let query = this._graphClient.api(apiUrl).version(version);
|
||||
if (selectProperties && selectProperties.length > 0) {
|
||||
query = query.select(selectProperties);
|
||||
}
|
||||
if (filter && filter.length > 0) {
|
||||
query = query.filter(filter);
|
||||
}
|
||||
if (expandProperties && expandProperties.length > 0) {
|
||||
query = query.expand(expandProperties);
|
||||
}
|
||||
|
||||
let callback = (error: GraphError, response: any, rawResponse?: any) => {
|
||||
if (error) {
|
||||
reject(error);
|
||||
} else {
|
||||
resolve(response);
|
||||
}
|
||||
};
|
||||
await query.get(callback);
|
||||
// tslint:disable-next-line: no-unused-expression
|
||||
typeof(content) === "object" && (content = JSON.stringify(content));
|
||||
// tslint:disable-next-line: no-unused-expression
|
||||
selectProperties && selectProperties.length > 0 && (query = query.select(selectProperties));
|
||||
// tslint:disable-next-line: no-unused-expression
|
||||
filter && filter.length > 0 && (query = query.filter(filter));
|
||||
// tslint:disable-next-line: no-unused-expression
|
||||
expandProperties && expandProperties.length > 0 && (query = query.expand(expandProperties));
|
||||
// tslint:disable-next-line: no-unused-expression
|
||||
count && (query = query.count(count));
|
||||
let callback = (error: GraphError, response: any, rawResponse?: any) => error ? reject(error) : resolve(response);
|
||||
//* ES2016
|
||||
["post", "patch"].includes(method) ? await query[method](content, callback) : await query[method](callback);
|
||||
});
|
||||
return p;
|
||||
}
|
||||
|
||||
public static async Patch(apiUrl: string, version: string = "v1.0", content: any): Promise<any> {
|
||||
var p = new Promise<string>(async (resolve, reject) => {
|
||||
if (typeof (content) === "object") {
|
||||
content = JSON.stringify(content);
|
||||
}
|
||||
|
||||
let query = this._graphClient.api(apiUrl).version(version);
|
||||
let callback = (error: GraphError, _response: any, rawResponse?: any) => {
|
||||
if (error) {
|
||||
reject(error);
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
};
|
||||
await query.update(content, callback);
|
||||
});
|
||||
return p;
|
||||
}
|
||||
|
||||
public static async Post(apiUrl: string, version: string = "v1.0", content: any): Promise<any> {
|
||||
var p = new Promise<string>(async (resolve, reject) => {
|
||||
if (typeof (content) === "object") {
|
||||
content = JSON.stringify(content);
|
||||
}
|
||||
|
||||
let query = this._graphClient.api(apiUrl).version(version);
|
||||
let callback = (error: GraphError, response: any, rawResponse?: any) => {
|
||||
if (error) {
|
||||
reject(error);
|
||||
} else {
|
||||
resolve(response);
|
||||
}
|
||||
};
|
||||
await query.post(content, callback);
|
||||
});
|
||||
return p;
|
||||
}
|
||||
|
||||
public static async Delete(apiUrl: string, version: string = "v1.0"): Promise<any> {
|
||||
var p = new Promise<string>(async (resolve, reject) => {
|
||||
let query = this._graphClient.api(apiUrl).version(version);
|
||||
let callback = (error: GraphError, response: any, rawResponse?: any) => {
|
||||
if (error) {
|
||||
reject(error);
|
||||
} else {
|
||||
resolve(response);
|
||||
}
|
||||
};
|
||||
await query.delete(callback);
|
||||
});
|
||||
return p;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
import { IDropdownOption } from "office-ui-fabric-react/lib/Dropdown";
|
||||
import { ICoordinates } from "@pnp/spfx-controls-react/lib/Map";
|
||||
|
||||
export interface ICMMDDropdownOption extends IDropdownOption {
|
||||
data: ICoordinates;
|
||||
parent?: string;
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
export interface IOption {
|
||||
key: string;
|
||||
text: string;
|
||||
parent: string;
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
export interface IProperty {
|
||||
key: string;
|
||||
value: string;
|
||||
}
|
@ -1,5 +1,4 @@
|
||||
import { IDescription } from "./IDescription";
|
||||
import { ILabel } from "./ILabel";
|
||||
import { IProperty, ILabel, IDescription } from ".";
|
||||
|
||||
export interface ITerm {
|
||||
id: string;
|
||||
@ -7,4 +6,5 @@ export interface ITerm {
|
||||
lastModifiedDateTime: Date;
|
||||
labels: ILabel[];
|
||||
descriptions: IDescription[];
|
||||
properties: IProperty[];
|
||||
}
|
@ -2,4 +2,5 @@ export { ILabel } from './ILabel';
|
||||
export { IDescription } from './IDescription';
|
||||
export { ITerm } from './ITerm';
|
||||
export { ITerms } from './ITerms';
|
||||
export { IOption } from './IOption';
|
||||
export { IProperty } from './IProperty';
|
||||
export { ICMMDDropdownOption } from './ICMMDDropdownOption';
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"extends": "./node_modules/@microsoft/rush-stack-compiler-2.9/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",
|
||||
"ES2016.Array.Include"
|
||||
]
|
||||
},
|
||||
"include": [
|
||||
"src/**/*.ts"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"lib"
|
||||
"src/**/*.ts",
|
||||
"src/**/*.tsx"
|
||||
]
|
||||
}
|
||||
|
@ -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,
|
||||
|
39
samples/react-lists-hide/.devcontainer/devcontainer.json
Normal file
39
samples/react-lists-hide/.devcontainer/devcontainer.json
Normal file
@ -0,0 +1,39 @@
|
||||
// For more information on how to run this SPFx project in a VS Code Remote Container, please visit https://aka.ms/spfx-devcontainer
|
||||
{
|
||||
"name": "SPFx 1.13.1",
|
||||
"image": "docker.io/m365pnp/spfx:1.13.1",
|
||||
// Set *default* container specific settings.json values on container create.
|
||||
"settings": {},
|
||||
// Add the IDs of extensions you want installed when the container is created.
|
||||
"extensions": [
|
||||
"editorconfig.editorconfig",
|
||||
"dbaeumer.vscode-eslint"
|
||||
],
|
||||
// Use 'forwardPorts' to make a list of ports inside the container available locally.
|
||||
"forwardPorts": [
|
||||
4321,
|
||||
35729
|
||||
],
|
||||
"portsAttributes": {
|
||||
"4321": {
|
||||
"protocol": "https",
|
||||
"label": "Manifest",
|
||||
"onAutoForward": "silent",
|
||||
"requireLocalPort": true
|
||||
},
|
||||
// Not needed for SPFx>= 1.12.1
|
||||
// "5432": {
|
||||
// "protocol": "https",
|
||||
// "label": "Workbench",
|
||||
// "onAutoForward": "silent"
|
||||
// },
|
||||
"35729": {
|
||||
"protocol": "https",
|
||||
"label": "LiveReload",
|
||||
"onAutoForward": "silent",
|
||||
"requireLocalPort": true
|
||||
}
|
||||
},
|
||||
"postCreateCommand": "bash .devcontainer/spfx-startup.sh",
|
||||
"remoteUser": "node"
|
||||
}
|
33
samples/react-lists-hide/.devcontainer/spfx-startup.sh
Normal file
33
samples/react-lists-hide/.devcontainer/spfx-startup.sh
Normal file
@ -0,0 +1,33 @@
|
||||
echo
|
||||
echo -e "\e[1;94mInstalling Node dependencies\e[0m"
|
||||
npm install
|
||||
|
||||
## commands to create dev certificate and copy it to the root folder of the project
|
||||
echo
|
||||
echo -e "\e[1;94mGenerating dev certificate\e[0m"
|
||||
gulp trust-dev-cert
|
||||
|
||||
# Convert the generated PEM certificate to a CER certificate
|
||||
openssl x509 -inform PEM -in ~/.rushstack/rushstack-serve.pem -outform DER -out ./spfx-dev-cert.cer
|
||||
|
||||
# Copy the PEM ecrtificate for non-Windows hosts
|
||||
cp ~/.rushstack/rushstack-serve.pem ./spfx-dev-cert.pem
|
||||
|
||||
## add *.cer to .gitignore to prevent certificates from being saved in repo
|
||||
if ! grep -Fxq '*.cer' ./.gitignore
|
||||
then
|
||||
echo "# .CER Certificates" >> .gitignore
|
||||
echo "*.cer" >> .gitignore
|
||||
fi
|
||||
|
||||
## add *.pem to .gitignore to prevent certificates from being saved in repo
|
||||
if ! grep -Fxq '*.pem' ./.gitignore
|
||||
then
|
||||
echo "# .PEM Certificates" >> .gitignore
|
||||
echo "*.pem" >> .gitignore
|
||||
fi
|
||||
|
||||
echo
|
||||
echo -e "\e[1;92mReady!\e[0m"
|
||||
|
||||
echo -e "\n\e[1;94m**********\nOptional: if you plan on using gulp serve, don't forget to add the container certificate to your local machine. Please visit https://aka.ms/spfx-devcontainer for more information\n**********"
|
2
samples/react-lists-hide/.gitattributes
vendored
Normal file
2
samples/react-lists-hide/.gitattributes
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
# Auto detect text files and perform LF normalization
|
||||
* text=auto
|
37
samples/react-lists-hide/.gitignore
vendored
Normal file
37
samples/react-lists-hide/.gitignore
vendored
Normal file
@ -0,0 +1,37 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
|
||||
# Dependency directories
|
||||
node_modules
|
||||
|
||||
# Build generated files
|
||||
dist
|
||||
lib
|
||||
release
|
||||
solution
|
||||
temp
|
||||
*.sppkg
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
|
||||
# OSX
|
||||
.DS_Store
|
||||
|
||||
# Visual Studio files
|
||||
.ntvs_analysis.dat
|
||||
.vs
|
||||
bin
|
||||
obj
|
||||
|
||||
# Resx Generated Code
|
||||
*.resx.ts
|
||||
|
||||
# Styles Generated Code
|
||||
*.scss.ts
|
||||
# .CER Certificates
|
||||
*.cer
|
||||
# .PEM Certificates
|
||||
*.pem
|
16
samples/react-lists-hide/.npmignore
Normal file
16
samples/react-lists-hide/.npmignore
Normal file
@ -0,0 +1,16 @@
|
||||
!dist
|
||||
config
|
||||
|
||||
gulpfile.js
|
||||
|
||||
release
|
||||
src
|
||||
temp
|
||||
|
||||
tsconfig.json
|
||||
tslint.json
|
||||
|
||||
*.log
|
||||
|
||||
.yo-rc.json
|
||||
.vscode
|
13
samples/react-lists-hide/.yo-rc.json
Normal file
13
samples/react-lists-hide/.yo-rc.json
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"@microsoft/generator-sharepoint": {
|
||||
"plusBeta": false,
|
||||
"isCreatingSolution": true,
|
||||
"environment": "spo",
|
||||
"version": "1.13.0",
|
||||
"libraryName": "hide-lists-wp",
|
||||
"libraryId": "6c179ebe-a9d0-4916-956f-0b9c6bfad50e",
|
||||
"packageManager": "npm",
|
||||
"isDomainIsolated": false,
|
||||
"componentType": "webpart"
|
||||
}
|
||||
}
|
103
samples/react-lists-hide/README.md
Normal file
103
samples/react-lists-hide/README.md
Normal file
@ -0,0 +1,103 @@
|
||||
# Hide Lists WebPart
|
||||
|
||||
## Summary
|
||||
|
||||
SPFx Web part to Hide/UnHide lists in a Site Collection's Site Contents Page.
|
||||
|
||||

|
||||
|
||||
As Site Admins we may need to hide some lists or libraries in Site Contents from other users who have access to the lists/libraries.
|
||||
|
||||
For example: we may have created a PowerApps form and need to hide master lists or Logs list which has to be kept hidden from end users though they have Read permissions or Edit permissions to the lists/libraries.
|
||||
|
||||
So that once the list is hidden, users cannot access the list directly from Site Contents or without knowing list name or list URL.
|
||||
|
||||
There are multiple ways to do this by using PowerShell Scripts, Rest API & MS Flows.
|
||||
|
||||
Here same functionality is achieved using SPFx web part, which we can just be added to a Site Collection and it will list out the lists and libraries in the site and Site Admin can Hide/Unhide lists with a simple button click.
|
||||
|
||||
This web part will be accessible only to users with Site Collection Admin access.
|
||||
|
||||
PnP JS library to get relevant SharePoint lists and libraries from current Site Collection and use "Hidden" property of lists to hide/Unhide.
|
||||
|
||||

|
||||
|
||||
## Compatibility
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||
-Incompatible-red.svg "SharePoint Server 2016 Feature Pack 2 requires SPFx 1.1")
|
||||

|
||||

|
||||

|
||||
|
||||
|
||||
## Applies to
|
||||
|
||||
* [SharePoint Framework](https://docs.microsoft.com/sharepoint/dev/spfx/sharepoint-framework-overview)
|
||||
* [Microsoft 365 tenant](https://docs.microsoft.com/sharepoint/dev/spfx/set-up-your-development-environment)
|
||||
|
||||
> Get your own free development tenant by subscribing to [Microsoft 365 developer program](http://aka.ms/o365devprogram)
|
||||
## Solution
|
||||
|
||||
|
||||
Solution|Author(s)
|
||||
--------|---------
|
||||
react-lists-hide | [Sandeep Unnikrishnan](https://github.com/SandeepDev365/)
|
||||
|
||||
## Version history
|
||||
|
||||
Version|Date|Comments
|
||||
-------|----|--------
|
||||
1.0|February 27, 2022|Initial release
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Ensure to have Site Collection Admin access to use this web part.
|
||||
|
||||
|
||||
## Minimal path to awesome
|
||||
|
||||
|
||||
* Clone this repository (or [download this solution as a .ZIP file](https://pnp.github.io/download-partial/?url=https://github.com/pnp/sp-dev-fx-webparts/tree/main/samples/react-lists-hide) then unzip it)
|
||||
* From your command line, change your current directory to the directory containing this sample (`react-lists-hide`, located under `samples`)
|
||||
* in the command line run:
|
||||
* `npm install`
|
||||
* **Update your SharePoint Site URL in `serve.json`**
|
||||
* `gulp serve`
|
||||
|
||||
> This sample can also be opened with [VS Code Remote Development](https://code.visualstudio.com/docs/remote/remote-overview). Visit https://aka.ms/spfx-devcontainer for further instructions.
|
||||
|
||||
|
||||
## Features
|
||||
|
||||
* List Out available Lists and Libraries based on template in current Site Collection
|
||||
* Hide/Unhide Lists on button click
|
||||
|
||||
|
||||
## Help
|
||||
|
||||
|
||||
We do not support samples, but 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're having issues building the solution, please run [spfx doctor](https://pnp.github.io/cli-microsoft365/cmd/spfx/spfx-doctor/) from within the solution folder to diagnose incompatibility issues with your environment.
|
||||
|
||||
You can try looking at [issues related to this sample](https://github.com/pnp/sp-dev-fx-webparts/issues?q=label%3A%22sample%3A%20react-lists-hide%22) 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=react-lists-hide) 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%2Csample%3A%20react-lists-hide&template=bug-report.yml&sample=react-lists-hide&authors=@SandeepDev365&title=react-lists-hide%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%3Aquestion%2Csample%3A%20react-lists-hide&template=question.yml&sample=react-lists-hide&authors=@SandeepDev365&title=react-lists-hide%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%3Aenhancement%2Csample%3A%20react-lists-hide&template=suggestion.yml&sample=react-lists-hide&authors=@SandeepDev365&title=react-lists-hide%20-%20).
|
||||
|
||||
|
||||
## 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.**
|
||||
|
||||
|
||||
<img src="https://pnptelemetry.azurewebsites.net/sp-dev-fx-webparts/samples/react-lists-hide" />
|
BIN
samples/react-lists-hide/assets/ListHideWebPart.jpg
Normal file
BIN
samples/react-lists-hide/assets/ListHideWebPart.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 169 KiB |
BIN
samples/react-lists-hide/assets/listHidewp.gif
Normal file
BIN
samples/react-lists-hide/assets/listHidewp.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 434 KiB |
56
samples/react-lists-hide/assets/sample.json
Normal file
56
samples/react-lists-hide/assets/sample.json
Normal file
@ -0,0 +1,56 @@
|
||||
[
|
||||
{
|
||||
"name": "pnp-sp-dev-spfx-web-parts-react-lists-hide",
|
||||
"source": "pnp",
|
||||
"title": "Hide Lists",
|
||||
"shortDescription": "SPFx Web part to Hide/UnHide lists in a Site Collection's Site Contents Page.",
|
||||
"url": "https://github.com/pnp/sp-dev-fx-webparts/tree/main/samples/react-lists-hide",
|
||||
"downloadUrl": "https://pnp.github.io/download-partial/?url=https://github.com/pnp/sp-dev-fx-webparts/tree/main/samples/react-lists-hide",
|
||||
"longDescription": [
|
||||
"SPFx Web part to Hide/UnHide lists in a Site Collection's Site Contents Page."
|
||||
],
|
||||
"creationDateTime": "2022-02-27",
|
||||
"updateDateTime": "2022-02-27",
|
||||
"products": [
|
||||
"SharePoint"
|
||||
],
|
||||
"metadata": [
|
||||
{
|
||||
"key": "CLIENT-SIDE-DEV",
|
||||
"value": "React"
|
||||
},
|
||||
{
|
||||
"key": "SPFX-VERSION",
|
||||
"value": "1.14"
|
||||
}
|
||||
],
|
||||
"thumbnails": [
|
||||
{
|
||||
"type": "image",
|
||||
"order": 100,
|
||||
"url": "https://github.com/pnp/sp-dev-fx-webparts/raw/main/samples/react-lists-hide/assets/ListHideWebPart.jpg",
|
||||
"alt": "Web Part Preview"
|
||||
},
|
||||
{
|
||||
"type": "image",
|
||||
"order": 101,
|
||||
"url": "https://github.com/pnp/sp-dev-fx-webparts/raw/main/samples/react-lists-hide/assets/listHidewp.gif",
|
||||
"alt": "Web Part Preview"
|
||||
}
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"gitHubAccount": "SandeepDev365",
|
||||
"pictureUrl": "https://github.com/SandeepDev365.png",
|
||||
"name": "Sandeep Unnikrishnan"
|
||||
}
|
||||
],
|
||||
"references": [
|
||||
{
|
||||
"name": "Build your first SharePoint client-side web part",
|
||||
"description": "Client-side web parts are client-side components that run in the context of a SharePoint page. Client-side web parts can be deployed to SharePoint environments that support the SharePoint Framework. You can also use modern JavaScript web frameworks, tools, and libraries to build them.",
|
||||
"url": "https://docs.microsoft.com/en-us/sharepoint/dev/spfx/web-parts/get-started/build-a-hello-world-web-part"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
18
samples/react-lists-hide/config/config.json
Normal file
18
samples/react-lists-hide/config/config.json
Normal file
@ -0,0 +1,18 @@
|
||||
{
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/config.2.0.schema.json",
|
||||
"version": "2.0",
|
||||
"bundles": {
|
||||
"hide-lists-web-part": {
|
||||
"components": [
|
||||
{
|
||||
"entrypoint": "./lib/webparts/hideLists/HideListsWebPart.js",
|
||||
"manifest": "./src/webparts/hideLists/HideListsWebPart.manifest.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"externals": {},
|
||||
"localizedResources": {
|
||||
"HideListsWebPartStrings": "lib/webparts/hideLists/loc/{locale}.js"
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
{
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/deploy-azure-storage.schema.json",
|
||||
"workingDir": "./release/assets/",
|
||||
"account": "<!-- STORAGE ACCOUNT NAME -->",
|
||||
"container": "hide-lists-wp",
|
||||
"accessKey": "<!-- ACCESS KEY -->"
|
||||
}
|
21
samples/react-lists-hide/config/package-solution.json
Normal file
21
samples/react-lists-hide/config/package-solution.json
Normal file
@ -0,0 +1,21 @@
|
||||
{
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/package-solution.schema.json",
|
||||
"solution": {
|
||||
"name": "hide-lists-wp-client-side-solution",
|
||||
"id": "6c179ebe-a9d0-4916-956f-0b9c6bfad50e",
|
||||
"version": "1.0.0.0",
|
||||
"includeClientSideAssets": true,
|
||||
"skipFeatureDeployment": true,
|
||||
"isDomainIsolated": false,
|
||||
"developer": {
|
||||
"name": "",
|
||||
"websiteUrl": "",
|
||||
"privacyUrl": "",
|
||||
"termsOfUseUrl": "",
|
||||
"mpnId": "Undefined-1.13.0"
|
||||
}
|
||||
},
|
||||
"paths": {
|
||||
"zippedPackage": "solution/hide-lists-wp.sppkg"
|
||||
}
|
||||
}
|
6
samples/react-lists-hide/config/serve.json
Normal file
6
samples/react-lists-hide/config/serve.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/core-build/serve.schema.json",
|
||||
"port": 4321,
|
||||
"https": true,
|
||||
"initialPage": "https://enter-your-SharePoint-site/_layouts/workbench.aspx"
|
||||
}
|
4
samples/react-lists-hide/config/write-manifests.json
Normal file
4
samples/react-lists-hide/config/write-manifests.json
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/write-manifests.schema.json",
|
||||
"cdnBasePath": "<!-- PATH TO CDN -->"
|
||||
}
|
16
samples/react-lists-hide/gulpfile.js
vendored
Normal file
16
samples/react-lists-hide/gulpfile.js
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
'use strict';
|
||||
|
||||
const build = require('@microsoft/sp-build-web');
|
||||
|
||||
build.addSuppression(`Warning - [sass] The local CSS class 'ms-Grid' is not camelCase and will not be type-safe.`);
|
||||
|
||||
var getTasks = build.rig.getTasks;
|
||||
build.rig.getTasks = function () {
|
||||
var result = getTasks.call(build.rig);
|
||||
|
||||
result.set('serve', result.get('serve-deprecated'));
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
build.initialize(require('gulp'));
|
21711
samples/react-lists-hide/package-lock.json
generated
Normal file
21711
samples/react-lists-hide/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
39
samples/react-lists-hide/package.json
Normal file
39
samples/react-lists-hide/package.json
Normal file
@ -0,0 +1,39 @@
|
||||
{
|
||||
"name": "hide-lists-wp",
|
||||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"main": "lib/index.js",
|
||||
"scripts": {
|
||||
"build": "gulp bundle",
|
||||
"clean": "gulp clean",
|
||||
"test": "gulp test"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fluentui/react": "^8.55.1",
|
||||
"@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/common": "^2.12.0",
|
||||
"@pnp/logging": "^2.12.0",
|
||||
"@pnp/odata": "^2.12.0",
|
||||
"@pnp/sp": "^2.12.0",
|
||||
"bootstrap": "^5.1.3",
|
||||
"office-ui-fabric-react": "7.174.1",
|
||||
"react": "16.13.1",
|
||||
"react-dom": "16.13.1",
|
||||
"react-table-6": "^6.11.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "16.9.51",
|
||||
"@types/react-dom": "16.9.8",
|
||||
"@microsoft/sp-build-web": "1.13.0",
|
||||
"@microsoft/sp-tslint-rules": "1.13.0",
|
||||
"@microsoft/sp-module-interfaces": "1.13.0",
|
||||
"@microsoft/rush-stack-compiler-3.9": "0.4.47",
|
||||
"gulp": "~4.0.2",
|
||||
"ajv": "~5.2.2",
|
||||
"@types/webpack-env": "1.13.1"
|
||||
}
|
||||
}
|
9
samples/react-lists-hide/src/Helper/Constant.ts
Normal file
9
samples/react-lists-hide/src/Helper/Constant.ts
Normal file
@ -0,0 +1,9 @@
|
||||
export const CallOutMessages: any = {
|
||||
hideList: "Do you want to Hide this List?",
|
||||
unHideList: "Do you want to Un-hide this List?"
|
||||
};
|
||||
|
||||
export const buttonTexts: any = {
|
||||
hide: "Hide",
|
||||
Unhide: "Un-hide"
|
||||
};
|
1
samples/react-lists-hide/src/index.ts
Normal file
1
samples/react-lists-hide/src/index.ts
Normal file
@ -0,0 +1 @@
|
||||
// A file is required to be in the root of the /src directory by the TypeScript compiler
|
@ -0,0 +1,28 @@
|
||||
{
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/spfx/client-side-web-part-manifest.schema.json",
|
||||
"id": "1b1dc257-2f1f-4255-a742-148a73e7be99",
|
||||
"alias": "HideListsWebPart",
|
||||
"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", "TeamsPersonalApp", "TeamsTab", "SharePointFullPage"],
|
||||
"supportsThemeVariants": true,
|
||||
|
||||
"preconfiguredEntries": [{
|
||||
"groupId": "5c03119e-3074-46fd-976b-c60198311f70", // Other
|
||||
"group": { "default": "Other" },
|
||||
"title": { "default": "HideLists" },
|
||||
"description": { "default": "This WebPart is used to show all lists in Site collection with an option to hide lists from site contents" },
|
||||
"officeFabricIconFontName": "Page",
|
||||
"properties": {
|
||||
"description": "HideLists"
|
||||
}
|
||||
}]
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
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 'HideListsWebPartStrings';
|
||||
import HideLists from './components/HideLists';
|
||||
import { sp } from '@pnp/sp';
|
||||
|
||||
export interface IHideListsWebPartProps {
|
||||
description: string;
|
||||
}
|
||||
|
||||
export default class HideListsWebPart extends BaseClientSideWebPart<IHideListsWebPartProps> {
|
||||
|
||||
private listsinSiteCollection = [];
|
||||
|
||||
protected onInit(): Promise<void> {
|
||||
return super.onInit().then(_ => {
|
||||
sp.setup({
|
||||
spfxContext: this.context
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public render(): void {
|
||||
const element: React.ReactElement = React.createElement(
|
||||
HideLists,
|
||||
{
|
||||
ctx: 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,74 @@
|
||||
@import '~office-ui-fabric-react/dist/sass/References.scss';
|
||||
|
||||
.hideLists {
|
||||
.container {
|
||||
max-width: 700px;
|
||||
margin: 0px auto;
|
||||
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), 0 25px 50px 0 rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.row {
|
||||
@include ms-Grid-row;
|
||||
@include ms-fontColor-white;
|
||||
background-color: $ms-color-themeDark;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.column {
|
||||
@include ms-Grid-col;
|
||||
@include ms-lg10;
|
||||
@include ms-xl8;
|
||||
@include ms-xlPush2;
|
||||
@include ms-lgPush1;
|
||||
}
|
||||
|
||||
.title {
|
||||
@include ms-font-xl;
|
||||
@include ms-fontColor-white;
|
||||
}
|
||||
|
||||
.subTitle {
|
||||
@include ms-font-l;
|
||||
@include ms-fontColor-white;
|
||||
}
|
||||
|
||||
.description {
|
||||
@include ms-font-l;
|
||||
@include ms-fontColor-white;
|
||||
}
|
||||
|
||||
.button {
|
||||
// Our button
|
||||
text-decoration: none;
|
||||
height: 32px;
|
||||
|
||||
// Primary Button
|
||||
min-width: 80px;
|
||||
background-color: $ms-color-themePrimary;
|
||||
border-color: $ms-color-themePrimary;
|
||||
color: $ms-color-white;
|
||||
|
||||
// Basic Button
|
||||
outline: transparent;
|
||||
position: relative;
|
||||
font-family: "Segoe UI WestEuropean","Segoe UI",-apple-system,BlinkMacSystemFont,Roboto,"Helvetica Neue",sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
font-size: $ms-font-size-m;
|
||||
font-weight: $ms-font-weight-regular;
|
||||
border-width: 0;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
padding: 0 16px;
|
||||
|
||||
.label {
|
||||
font-weight: $ms-font-weight-semibold;
|
||||
font-size: $ms-font-size-m;
|
||||
height: 32px;
|
||||
line-height: 32px;
|
||||
margin: 0 4px;
|
||||
vertical-align: top;
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,242 @@
|
||||
import * as React from 'react';
|
||||
import styles from './HideLists.module.scss';
|
||||
import { IHideListsProps } from './IHideListsProps';
|
||||
import { IHideListsState } from './IHideListsState';
|
||||
import { sp } from "@pnp/sp";
|
||||
import "@pnp/sp/webs";
|
||||
import "@pnp/sp/lists";
|
||||
import "@pnp/sp/site-users/web";
|
||||
import ReactTable from "react-table-6";
|
||||
import 'react-table-6/react-table.css';
|
||||
import 'bootstrap/dist/css/bootstrap.min.css';
|
||||
import { DefaultButton, FocusTrapCallout } from '@microsoft/office-ui-fabric-react-bundle';
|
||||
import { CallOutMessages, buttonTexts } from "../../../Helper/Constant";
|
||||
import { FocusZone, FocusZoneTabbableElements, MessageBarType, PrimaryButton, Stack } from 'office-ui-fabric-react';
|
||||
import { MessageBar, MessageBarButton } from 'office-ui-fabric-react';
|
||||
|
||||
export default class HideLists extends React.Component<IHideListsProps, IHideListsState> {
|
||||
private columns = [
|
||||
{
|
||||
Header: "List Name",
|
||||
accessor: "Title",
|
||||
headerStyle: { whiteSpace: 'nowrap' },
|
||||
style: { whiteSpace: 'normal' },
|
||||
sortable: true,
|
||||
filterable: true,
|
||||
width: 150,
|
||||
Cell: row => (
|
||||
<div className='trucateData'>{row.original.Title}</div>
|
||||
)
|
||||
},
|
||||
{
|
||||
Header: "List Type",
|
||||
accessor: "BaseTemplate",
|
||||
headerStyle: { whiteSpace: 'nowrap' },
|
||||
style: { whiteSpace: 'normal' },
|
||||
sortable: true,
|
||||
filterable: true,
|
||||
width: 120,
|
||||
Cell: row => (
|
||||
<div className='trucateData'>{row.original.BaseTemplate}</div>
|
||||
)
|
||||
},
|
||||
{
|
||||
Header: "List GUID",
|
||||
accessor: "Id",
|
||||
headerStyle: { whiteSpace: 'nowrap' },
|
||||
style: { whiteSpace: 'normal' },
|
||||
sortable: true,
|
||||
filterable: true,
|
||||
Cell: row => (
|
||||
<div className='trucateData'>{row.original.Id}</div>
|
||||
)
|
||||
},
|
||||
{
|
||||
Header: "Is Hidden",
|
||||
accessor: "Hidden",
|
||||
headerStyle: { whiteSpace: 'nowrap' },
|
||||
style: { whiteSpace: 'normal' },
|
||||
sortable: true,
|
||||
filterable: true,
|
||||
width: 100,
|
||||
Cell: row => (
|
||||
<div className='trucateData'>{row.original.Hidden.toString()}</div>
|
||||
)
|
||||
},
|
||||
{
|
||||
Header: "Action",
|
||||
accessor: "",
|
||||
headerStyle: { whiteSpace: 'nowrap' },
|
||||
style: { whiteSpace: 'normal', color: '#0460A9', fontWeight: 'bold', flexWrap: 'wrap' },
|
||||
width: 140,
|
||||
Cell: row => (
|
||||
<>
|
||||
{
|
||||
row.original.Hidden ?
|
||||
<DefaultButton id={"btn" + row.index} onClick={() => this.actionbtnClicked(row, buttonTexts.Unhide)}>{buttonTexts.Unhide}</DefaultButton>
|
||||
:
|
||||
<DefaultButton id={"btn" + row.index} onClick={() => this.actionbtnClicked(row, buttonTexts.hide)}>{buttonTexts.hide}</DefaultButton>
|
||||
}
|
||||
</>
|
||||
)
|
||||
}
|
||||
];
|
||||
private tableInstance;
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
data: [],
|
||||
rowData: null,
|
||||
user: null,
|
||||
isCalloutVisible: false,
|
||||
isConfirmCalloutMessage: "",
|
||||
isConfirmCallOutVisible: false
|
||||
};
|
||||
}
|
||||
|
||||
public async componentDidMount() {
|
||||
await this.GetLists();
|
||||
await this.checkifUserisAdmin();
|
||||
}
|
||||
|
||||
private async checkifUserisAdmin() {
|
||||
await sp.web.currentUser().then((userObj) => {
|
||||
this.setState({ user: userObj }, () => {
|
||||
console.log("user", this.state.user);
|
||||
console.log("isAdmin", this.state.user.IsSiteAdmin);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private async unHideList() {
|
||||
let row = this.state.rowData;
|
||||
console.log("In UnHideList method");
|
||||
console.log("row", row);
|
||||
console.log("List Title - ", row.original.Title);
|
||||
console.log("List GUID - ", row.original.Id);
|
||||
|
||||
try {
|
||||
await sp.web.lists.getById(row.original.Id).update({
|
||||
Hidden: false
|
||||
});
|
||||
await this.GetLists();
|
||||
}
|
||||
catch (ex) {
|
||||
console.log('Error', ex);
|
||||
}
|
||||
}
|
||||
|
||||
private async hideList() {
|
||||
let row = this.state.rowData;
|
||||
console.log("In HideList method");
|
||||
console.log("row", row);
|
||||
console.log("List Title - ", row.original.Title);
|
||||
console.log("List GUID - ", row.original.Id);
|
||||
|
||||
try {
|
||||
await sp.web.lists.getById(row.original.Id).update({
|
||||
Hidden: true
|
||||
});
|
||||
await this.GetLists();
|
||||
}
|
||||
catch (ex) {
|
||||
console.log('Error', ex);
|
||||
}
|
||||
}
|
||||
|
||||
private async GetLists(): Promise<any> {
|
||||
return sp.web.lists.filter("BaseTemplate eq 100 or BaseTemplate eq 101 or BaseTemplate eq 106 or BaseTemplate eq 119").get().then((lsData) => { //filter("Hidden eq false and BaseType ne 1")
|
||||
console.log("Total number of lists are " + lsData.length);
|
||||
console.log("data", lsData);
|
||||
this.setState({ data: lsData });
|
||||
});
|
||||
}
|
||||
|
||||
private actionbtnClicked = (row, btnText) => {
|
||||
switch (btnText) {
|
||||
case buttonTexts.hide: this.setState({ isConfirmCallOutVisible: true, isConfirmCalloutMessage: CallOutMessages.hideList, rowData: row }); break;
|
||||
case buttonTexts.Unhide: this.setState({ isConfirmCallOutVisible: true, isConfirmCalloutMessage: CallOutMessages.unHideList, rowData: row }); break;
|
||||
}
|
||||
}
|
||||
|
||||
private _onCalloutDismiss = () => {
|
||||
this.setState({ isCalloutVisible: false, isConfirmCalloutMessage: "", isConfirmCallOutVisible: false });
|
||||
}
|
||||
|
||||
private onConfirmationMessageYesClicked = (event) => {
|
||||
switch (this.state.isConfirmCalloutMessage) {
|
||||
case CallOutMessages.hideList: this.hideList(); this._onCalloutDismiss(); break;
|
||||
case CallOutMessages.unHideList: this.unHideList(); this._onCalloutDismiss(); break;
|
||||
}
|
||||
}
|
||||
|
||||
private onConfirmationMessageNoClicked = (event) => {
|
||||
this._onCalloutDismiss();
|
||||
}
|
||||
|
||||
public render(): React.ReactElement {
|
||||
let { isCalloutVisible, isConfirmCallOutVisible, isConfirmCalloutMessage, data, user } = this.state;
|
||||
let btnId = this.state.rowData ? "btn" + this.state.rowData.index : "";
|
||||
console.log("columns", this.columns);
|
||||
console.log("data", data);
|
||||
return (
|
||||
<div>
|
||||
{
|
||||
user && user.IsSiteAdmin ?
|
||||
<div>
|
||||
<div>
|
||||
Site Url: <b>{this.props.ctx.pageContext.web.absoluteUrl}</b><br />
|
||||
Total Number of lists in the Site are <b>{data.length}</b>
|
||||
</div>
|
||||
<br />
|
||||
<ReactTable
|
||||
columns={this.columns}
|
||||
data={data}
|
||||
minRows={0}
|
||||
defaultPageSize={5}
|
||||
pageSizeOptions={[5, 10, 15]}
|
||||
noDataText={"Sorry, No data to display!!!"}
|
||||
defaultFilterMethod={(filter, row, column) => {
|
||||
const id = filter.pivotId || filter.id;
|
||||
return row[id] !== undefined ? String(row[id]).toLowerCase().indexOf(filter.value.toLowerCase()) !== -1 : true;
|
||||
}}
|
||||
/>
|
||||
|
||||
{isConfirmCallOutVisible && (
|
||||
<FocusTrapCallout
|
||||
className='ms-CalloutExample-callout'
|
||||
ariaLabelledBy={'callout-label-1'}
|
||||
ariaDescribedBy={'callout-description-1'}
|
||||
role={'alertdialog'}
|
||||
gapSpace={0}
|
||||
target={`#${btnId}`}
|
||||
onDismiss={this._onCalloutDismiss}
|
||||
setInitialFocus={true}
|
||||
>
|
||||
<MessageBar messageBarType={MessageBarType.warning} className='saveChanges' isMultiline={true} actions={
|
||||
<FocusZone handleTabKey={FocusZoneTabbableElements.all} isCircularNavigation>
|
||||
<Stack className='button custButton' gap={8} horizontal>
|
||||
<PrimaryButton onClick={(event) => this.onConfirmationMessageYesClicked(event)}>Yes</PrimaryButton>
|
||||
<DefaultButton onClick={(event) => this.onConfirmationMessageNoClicked(event)}>No</DefaultButton>
|
||||
</Stack>
|
||||
</FocusZone>
|
||||
}>
|
||||
{isConfirmCalloutMessage}
|
||||
</MessageBar>
|
||||
</FocusTrapCallout>
|
||||
)}
|
||||
</div>
|
||||
:
|
||||
<div>
|
||||
<MessageBar messageBarType={MessageBarType.error} className='saveChanges' isMultiline={true}>
|
||||
Sorry!!! This tool is only for Site Admins...
|
||||
</MessageBar>
|
||||
</div>
|
||||
}
|
||||
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
export interface IHideListsProps {
|
||||
ctx: any;
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
import { IListInfo } from '@pnp/sp/lists';
|
||||
|
||||
export interface IHideListsState {
|
||||
data: IListInfo[];
|
||||
rowData: any;
|
||||
user: any;
|
||||
isCalloutVisible: boolean;
|
||||
isConfirmCalloutMessage: string;
|
||||
isConfirmCallOutVisible: boolean;
|
||||
}
|
7
samples/react-lists-hide/src/webparts/hideLists/loc/en-us.js
vendored
Normal file
7
samples/react-lists-hide/src/webparts/hideLists/loc/en-us.js
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
define([], function() {
|
||||
return {
|
||||
"PropertyPaneDescription": "Description",
|
||||
"BasicGroupName": "Group Name",
|
||||
"DescriptionFieldLabel": "Description Field"
|
||||
}
|
||||
});
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user