Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions samples/react-kpi-scorecard/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Logs
logs
*.log
npm-debug.log*

# Dependencies and build output
node_modules
dist
lib
lib-dts
lib-commonjs
lib-esm
jest-output
release
solution
temp
*.sppkg
.heft
coverage

# Local files
.DS_Store
*.scss.ts
6 changes: 6 additions & 0 deletions samples/react-kpi-scorecard/.npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Ignore everything by default
**
!README.md
!assets/**
!lib/**
!package.json
1 change: 1 addition & 0 deletions samples/react-kpi-scorecard/.nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
22.14.0
18 changes: 18 additions & 0 deletions samples/react-kpi-scorecard/.yo-rc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"@microsoft/generator-sharepoint": {
"plusBeta": false,
"isCreatingSolution": true,
"version": "1.23.2",
"nodeVersion": "22.14.0",
"libraryName": "react-kpi-scorecard",
"libraryId": "6b1b3b8f-7f5d-4f34-8d2d-0b7d9f0d1e21",
"environment": "spo",
"packageManager": "npm",
"solutionName": "react-kpi-scorecard",
"solutionShortDescription": "Read-only operational KPI scorecard",
"skipFeatureDeployment": true,
"isDomainIsolated": false,
"componentType": "webpart",
"useGulp": false
}
}
51 changes: 51 additions & 0 deletions samples/react-kpi-scorecard/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# KPI Scorecard

## Summary

This React SharePoint Framework web part displays read-only operational KPIs from a SharePoint list. It shows the latest value and target for each KPI, derives threshold and trend status from the data, and provides accessible loading, empty, setup, and error states. It uses PnPjs and Fluent UI 9 without a chart library.

## Compatibility

![SPFx 1.23.2](https://img.shields.io/badge/SPFx-1.23.2-green.svg)
![Node.js v22.14.0](https://img.shields.io/badge/Node.js-v22.14.0-green.svg)
![Compatible with SharePoint Online](https://img.shields.io/badge/SharePoint%20Online-Compatible-green.svg)
![Hosted Workbench Compatible](https://img.shields.io/badge/Hosted%20Workbench-Compatible-green.svg)

Use Node.js `>=22.14.0 <23.0.0`. See the [SPFx compatibility matrix](https://aka.ms/spfx-matrix) before using a different SPFx or Node.js version. The local workbench is not supported by current SPFx versions; use the hosted SharePoint workbench.

## SharePoint list setup

Create a list named `KPI Observations` with one row per KPI observation. Use these columns and internal names:

| Display name | Type | Required |
| --- | --- | --- |
| Title | Single line of text | Yes |
| Value | Number | No |
| Target | Number | No |
| Status | Single line of text | No |
| Date | Date and time | No |

Add multiple dated rows with the same `Title` to calculate a deterministic change from the latest to the previous observation. The web part only reads list items.

## Configuration

In the property pane, set the list title and the internal names for the title, value, target, and status fields. The date field is optional. `Root web path` can be blank for the current web or a site-relative path such as `/sites/Operations`; `Date filter` is optional and includes observations on or after a `YYYY-MM-DD` date.

## Local validation

```bash
npm install
npm test
npm run build
```

To run the hosted workbench development server, use `npm start` and open the URL shown by Heft.

## Limitations

- Each request is capped at 100 SharePoint list items and the UI displays at most six KPI cards.
- Results are grouped by exact KPI title; the latest date (then highest SharePoint ID) is current.
- Values and targets are numeric fields. Missing or invalid values are shown as unavailable.
- The web part requires permission to read the configured web and list and does not create or update data.

<img src="https://m365-visitor-stats.azurewebsites.net/sp-dev-fx-webparts/samples/react-kpi-scorecard" />
52 changes: 52 additions & 0 deletions samples/react-kpi-scorecard/assets/sample.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
[
{
"name": "pnp-sp-dev-spfx-web-parts-react-kpi-scorecard",
"source": "pnp",
"title": "Operational KPI Scorecard",
"shortDescription": "A read-only React web part that displays operational KPIs from a SharePoint list.",
"url": "https://github.com/pnp/sp-dev-fx-webparts/tree/main/samples/react-kpi-scorecard",
"downloadUrl": "https://pnp.github.io/download-partial/?url=https://github.com/pnp/sp-dev-fx-webparts/tree/main/samples/react-kpi-scorecard",
"longDescription": [
"This SharePoint Framework sample uses PnPjs and Fluent UI 9 to display current KPI values, targets, statuses, and deterministic trends from a SharePoint list. It is read-only, validates configuration, bounds list queries, and provides accessible loading and error states."
],
"creationDateTime": "2026-08-30",
"updateDateTime": "2026-08-30",
"products": [
"SharePoint"
],
"metadata": [
{
"key": "SAMPLE-TYPE",
"value": "SPFx-WebPart"
},
{
"key": "CLIENT-SIDE-DEV",
"value": "React"
},
{
"key": "SPFX-VERSION",
"value": "1.23.2"
}
],
"thumbnails": [],
"authors": [
{
"gitHubAccount": "vystartasv",
"pictureUrl": "https://github.com/vystartasv.png",
"name": "Vilius Vystartas"
}
],
"references": [
{
"name": "Build your first SharePoint client-side web part",
"description": "Client-side web parts run in the context of a SharePoint page and can use modern JavaScript frameworks and libraries.",
"url": "https://learn.microsoft.com/sharepoint/dev/spfx/web-parts/get-started/build-a-hello-world-web-part"
},
{
"name": "PnPjs",
"description": "PnPjs provides fluent APIs for working with SharePoint and Microsoft 365.",
"url": "https://pnp.github.io/pnpjs/"
}
]
}
]
18 changes: 18 additions & 0 deletions samples/react-kpi-scorecard/config/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/config.2.0.schema.json",
"version": "2.0",
"bundles": {
"kpi-scorecard-web-part": {
"components": [
{
"entrypoint": "./lib/webparts/kpiScorecard/KpiScorecardWebPart.js",
"manifest": "./src/webparts/kpiScorecard/KpiScorecardWebPart.manifest.json"
}
]
}
},
"externals": {},
"localizedResources": {
"KpiScorecardWebPartStrings": "lib/webparts/kpiScorecard/loc/{locale}.js"
}
}
3 changes: 3 additions & 0 deletions samples/react-kpi-scorecard/config/jest.config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"extends": "@microsoft/spfx-web-build-rig/profiles/default/config/jest.config.json"
}
37 changes: 37 additions & 0 deletions samples/react-kpi-scorecard/config/package-solution.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/package-solution.schema.json",
"solution": {
"name": "react-kpi-scorecard-client-side-solution",
"title": "Operational KPI Scorecard",
"id": "6b1b3b8f-7f5d-4f34-8d2d-0b7d9f0d1e21",
"version": "1.0.0.0",
"includeClientSideAssets": true,
"skipFeatureDeployment": true,
"isDomainIsolated": false,
"developer": {
"name": "Vilius Vystartas",
"websiteUrl": "https://github.com/vystartasv",
"privacyUrl": "",
"termsOfUseUrl": "",
"mpnId": "Undefined-1.23.2"
},
"metadata": {
"shortDescription": { "default": "Read-only operational KPI scorecard" },
"longDescription": { "default": "Display current KPI values, targets, statuses, and deterministic trends from a SharePoint list." },
"screenshotPaths": [],
"videoUrl": "",
"categories": []
},
"features": [
{
"title": "Operational KPI Scorecard Feature",
"description": "Adds the Operational KPI Scorecard web part.",
"id": "4d6c66de-0d39-4e53-b97e-e42e9974cc5c",
"version": "1.0.0.0"
}
]
},
"paths": {
"zippedPackage": "solution/react-kpi-scorecard.sppkg"
}
}
4 changes: 4 additions & 0 deletions samples/react-kpi-scorecard/config/rig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/rig-package/rig.schema.json",
"rigPackageName": "@microsoft/spfx-web-build-rig"
}
4 changes: 4 additions & 0 deletions samples/react-kpi-scorecard/config/sass.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/heft/v0/heft-sass-plugin.schema.json",
"extends": "@microsoft/spfx-web-build-rig/profiles/default/config/sass.json"
}
6 changes: 6 additions & 0 deletions samples/react-kpi-scorecard/config/serve.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/spfx-serve.schema.json",
"port": 4321,
"https": true,
"initialPage": "https://{tenantDomain}/_layouts/workbench.aspx"
}
7 changes: 7 additions & 0 deletions samples/react-kpi-scorecard/config/typescript.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"extends": "@microsoft/spfx-web-build-rig/profiles/default/config/typescript.json",
"staticAssetsToCopy": {
"fileExtensions": [".resx", ".jpg", ".png", ".woff", ".eot", ".ttf", ".svg", ".gif"],
"includeGlobs": ["webparts/*/loc/*.js"]
}
}
14 changes: 14 additions & 0 deletions samples/react-kpi-scorecard/eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
const spfxProfile = require('@microsoft/eslint-config-spfx/lib/flat-profiles/react');

module.exports = [
...spfxProfile,
{
files: ['**/*.ts', '**/*.tsx'],
languageOptions: {
parserOptions: {
tsconfigRootDir: __dirname,
project: './tsconfig.json'
}
}
}
];
Loading
Loading