diff --git a/samples/react-enhanced-page-properties/package-lock.json b/samples/react-enhanced-page-properties/package-lock.json index 7b3fea0d5..1f50ce350 100644 --- a/samples/react-enhanced-page-properties/package-lock.json +++ b/samples/react-enhanced-page-properties/package-lock.json @@ -15,6 +15,7 @@ "@microsoft/sp-office-ui-fabric-core": "1.17.4", "@microsoft/sp-property-pane": "1.17.4", "@microsoft/sp-webpart-base": "1.17.4", + "@pnp/sp": "^3.17.0", "office-ui-fabric-react": "^7.199.1", "react": "17.0.1", "react-dom": "17.0.1", @@ -8507,6 +8508,70 @@ "node": ">= 8" } }, + "node_modules/@pnp/core": { + "version": "3.17.0", + "resolved": "https://registry.npmjs.org/@pnp/core/-/core-3.17.0.tgz", + "integrity": "sha512-h+nu1eHEQ0VpiRcLDQjPyVJHnrHruFJ/v8ZsSbJx1Vg2EoP/X5wDaZNXSjEmF3Xy3yD9aURDkdMw7eVb7PMfEw==", + "dependencies": { + "tslib": "2.4.1" + }, + "engines": { + "node": ">=14.15.1" + }, + "funding": { + "type": "individual", + "url": "https://github.com/sponsors/patrick-rodgers/" + } + }, + "node_modules/@pnp/core/node_modules/tslib": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" + }, + "node_modules/@pnp/queryable": { + "version": "3.17.0", + "resolved": "https://registry.npmjs.org/@pnp/queryable/-/queryable-3.17.0.tgz", + "integrity": "sha512-kF2fi1pRZr70jGi9qrlA7wLi9Eh1AS+szPGT8C665cko18pahY8OLd8ra8d08Cw8TTuNG/AvJ6Z4BU1I3kSWYg==", + "dependencies": { + "@pnp/core": "3.17.0", + "tslib": "2.4.1" + }, + "engines": { + "node": ">=14.15.1" + }, + "funding": { + "type": "individual", + "url": "https://github.com/sponsors/patrick-rodgers/" + } + }, + "node_modules/@pnp/queryable/node_modules/tslib": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" + }, + "node_modules/@pnp/sp": { + "version": "3.17.0", + "resolved": "https://registry.npmjs.org/@pnp/sp/-/sp-3.17.0.tgz", + "integrity": "sha512-PTeLI+D5oddALX+Xogs9PzcebfSXdidS0QU8Ral7HU8797lFSzlMx3FTG+nAPHTLerTHsUvAAtkmCw1rI6MBXQ==", + "hasInstallScript": true, + "dependencies": { + "@pnp/core": "3.17.0", + "@pnp/queryable": "3.17.0", + "tslib": "2.4.1" + }, + "engines": { + "node": ">=14.15.1" + }, + "funding": { + "type": "individual", + "url": "https://github.com/sponsors/patrick-rodgers/" + } + }, + "node_modules/@pnp/sp/node_modules/tslib": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" + }, "node_modules/@pnpm/crypto.base32-hash": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@pnpm/crypto.base32-hash/-/crypto.base32-hash-1.0.1.tgz", @@ -43468,6 +43533,54 @@ } } }, + "@pnp/core": { + "version": "3.17.0", + "resolved": "https://registry.npmjs.org/@pnp/core/-/core-3.17.0.tgz", + "integrity": "sha512-h+nu1eHEQ0VpiRcLDQjPyVJHnrHruFJ/v8ZsSbJx1Vg2EoP/X5wDaZNXSjEmF3Xy3yD9aURDkdMw7eVb7PMfEw==", + "requires": { + "tslib": "2.4.1" + }, + "dependencies": { + "tslib": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" + } + } + }, + "@pnp/queryable": { + "version": "3.17.0", + "resolved": "https://registry.npmjs.org/@pnp/queryable/-/queryable-3.17.0.tgz", + "integrity": "sha512-kF2fi1pRZr70jGi9qrlA7wLi9Eh1AS+szPGT8C665cko18pahY8OLd8ra8d08Cw8TTuNG/AvJ6Z4BU1I3kSWYg==", + "requires": { + "@pnp/core": "3.17.0", + "tslib": "2.4.1" + }, + "dependencies": { + "tslib": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" + } + } + }, + "@pnp/sp": { + "version": "3.17.0", + "resolved": "https://registry.npmjs.org/@pnp/sp/-/sp-3.17.0.tgz", + "integrity": "sha512-PTeLI+D5oddALX+Xogs9PzcebfSXdidS0QU8Ral7HU8797lFSzlMx3FTG+nAPHTLerTHsUvAAtkmCw1rI6MBXQ==", + "requires": { + "@pnp/core": "3.17.0", + "@pnp/queryable": "3.17.0", + "tslib": "2.4.1" + }, + "dependencies": { + "tslib": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" + } + } + }, "@pnpm/crypto.base32-hash": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@pnpm/crypto.base32-hash/-/crypto.base32-hash-1.0.1.tgz", diff --git a/samples/react-enhanced-page-properties/package.json b/samples/react-enhanced-page-properties/package.json index c27af48f4..ecfb37bc5 100644 --- a/samples/react-enhanced-page-properties/package.json +++ b/samples/react-enhanced-page-properties/package.json @@ -13,33 +13,34 @@ "serve": "gulp bundle --custom-serve --max_old_space_size=4096 && fast-serve" }, "dependencies": { - "tslib": "2.3.1", - "react": "17.0.1", - "react-dom": "17.0.1", - "office-ui-fabric-react": "^7.199.1", "@fluentui/react": "^7.199.1", - "@microsoft/sp-core-library": "1.17.4", "@microsoft/sp-component-base": "1.17.4", + "@microsoft/sp-core-library": "1.17.4", + "@microsoft/sp-lodash-subset": "1.17.4", + "@microsoft/sp-office-ui-fabric-core": "1.17.4", "@microsoft/sp-property-pane": "1.17.4", "@microsoft/sp-webpart-base": "1.17.4", - "@microsoft/sp-lodash-subset": "1.17.4", - "@microsoft/sp-office-ui-fabric-core": "1.17.4" + "@pnp/sp": "^3.17.0", + "office-ui-fabric-react": "^7.199.1", + "react": "17.0.1", + "react-dom": "17.0.1", + "tslib": "2.3.1" }, "devDependencies": { - "@microsoft/rush-stack-compiler-4.5": "0.5.0", - "@rushstack/eslint-config": "2.5.1", - "@microsoft/eslint-plugin-spfx": "1.17.4", "@microsoft/eslint-config-spfx": "1.17.4", + "@microsoft/eslint-plugin-spfx": "1.17.4", + "@microsoft/rush-stack-compiler-4.5": "0.5.0", "@microsoft/sp-build-web": "1.17.4", + "@microsoft/sp-module-interfaces": "1.17.4", + "@rushstack/eslint-config": "2.5.1", + "@types/react": "17.0.45", + "@types/react-dom": "17.0.17", "@types/webpack-env": "~1.15.2", "ajv": "^6.12.5", "eslint": "8.7.0", - "gulp": "4.0.2", - "typescript": "4.5.5", - "@types/react": "17.0.45", - "@types/react-dom": "17.0.17", "eslint-plugin-react-hooks": "4.3.0", - "@microsoft/sp-module-interfaces": "1.17.4", - "spfx-fast-serve-helpers": "~1.17.0" + "gulp": "4.0.2", + "spfx-fast-serve-helpers": "~1.17.0", + "typescript": "4.5.5" } -} \ No newline at end of file +} diff --git a/samples/react-enhanced-page-properties/src/webparts/enhancedPageProperties/EnhancedPagePropertiesWebPart.ts b/samples/react-enhanced-page-properties/src/webparts/enhancedPageProperties/EnhancedPagePropertiesWebPart.ts index fa8d1261a..d7222fe12 100644 --- a/samples/react-enhanced-page-properties/src/webparts/enhancedPageProperties/EnhancedPagePropertiesWebPart.ts +++ b/samples/react-enhanced-page-properties/src/webparts/enhancedPageProperties/EnhancedPagePropertiesWebPart.ts @@ -1,91 +1,91 @@ -import * as React from 'react'; -import * as ReactDom from 'react-dom'; -import { Version } from '@microsoft/sp-core-library'; +import "@pnp/sp/webs"; +import "@pnp/sp/lists"; +import "@pnp/sp/items"; +import "@pnp/sp/fields"; + +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 { IReadonlyTheme } from '@microsoft/sp-component-base'; + PropertyPaneTextField, +} from "@microsoft/sp-property-pane"; +import { BaseClientSideWebPart } from "@microsoft/sp-webpart-base"; +import { SPFI, spfi, SPFx } from "@pnp/sp"; -import * as strings from 'EnhancedPagePropertiesWebPartStrings'; -import EnhancedPageProperties from './components/EnhancedPageProperties'; -import { IEnhancedPagePropertiesProps } from './components/IEnhancedPagePropertiesProps'; +import EnhancedPageProperties from "./components/EnhancedPageProperties"; +import { IEnhancedPagePropertiesProps } from "./components/IEnhancedPagePropertiesProps"; export interface IEnhancedPagePropertiesWebPartProps { - description: string; + title: string; + fields: string; +} + +export interface propertyItem { + label: string; + field: string; + value: string; + isAvailable: boolean; } export default class EnhancedPagePropertiesWebPart extends BaseClientSideWebPart { + private readonly docLibTitle = 'Site Pages'; + private _sp: SPFI; - private _isDarkTheme: boolean = false; - private _environmentMessage: string = ''; - - public render(): void { - const element: React.ReactElement = React.createElement( - EnhancedPageProperties, - { - description: this.properties.description, - isDarkTheme: this._isDarkTheme, - environmentMessage: this._environmentMessage, - hasTeamsContext: !!this.context.sdks.microsoftTeams, - userDisplayName: this.context.pageContext.user.displayName - } - ); + public async render(): Promise { + const items: propertyItem[] = await this.getCurrentPageProperties(); + const element: React.ReactElement = + React.createElement(EnhancedPageProperties, { + title: this.properties.title, + items, + }); ReactDom.render(element, this.domElement); } - protected onInit(): Promise { - return this._getEnvironmentMessage().then(message => { - this._environmentMessage = message; - }); + protected async onInit(): Promise { + await super.onInit(); + this._sp = spfi().using(SPFx(this.context)); } - - - private _getEnvironmentMessage(): Promise { - if (!!this.context.sdks.microsoftTeams) { // running in Teams, office.com or Outlook - return this.context.sdks.microsoftTeams.teamsJs.app.getContext() - .then(context => { - let environmentMessage: string = ''; - switch (context.app.host.name) { - case 'Office': // running in Office - environmentMessage = this.context.isServedFromLocalhost ? strings.AppLocalEnvironmentOffice : strings.AppOfficeEnvironment; - break; - case 'Outlook': // running in Outlook - environmentMessage = this.context.isServedFromLocalhost ? strings.AppLocalEnvironmentOutlook : strings.AppOutlookEnvironment; - break; - case 'Teams': // running in Teams - environmentMessage = this.context.isServedFromLocalhost ? strings.AppLocalEnvironmentTeams : strings.AppTeamsTabEnvironment; - break; - default: - throw new Error('Unknown host'); - } - - return environmentMessage; - }); - } - - return Promise.resolve(this.context.isServedFromLocalhost ? strings.AppLocalEnvironmentSharePoint : strings.AppSharePointEnvironment); + protected convertSelectedFieldsString(): string[] { + return this.properties.fields.split(",").map((field) => field.trim()); } - protected onThemeChanged(currentTheme: IReadonlyTheme | undefined): void { - if (!currentTheme) { - return; + protected async getCurrentPageProperties(): Promise { + // Get available fields in the Document Library + const availableFields = await this._sp.web.lists + .getByTitle(this.docLibTitle) + .fields(); + // Filter to only non hidden fields + const filteredAvailableFields: Map = new Map(); + for (let i = 0; i < availableFields.length; i++) { + const field = availableFields[i]; + if (field.Hidden) continue; + filteredAvailableFields.set(field.InternalName, field.Title); } - this._isDarkTheme = !!currentTheme.isInverted; - const { - semanticColors - } = currentTheme; - - if (semanticColors) { - this.domElement.style.setProperty('--bodyText', semanticColors.bodyText || null); - this.domElement.style.setProperty('--link', semanticColors.link || null); - this.domElement.style.setProperty('--linkHovered', semanticColors.linkHovered || null); + const selectedFields = this.convertSelectedFieldsString(); + const propertyItems: propertyItem[] = []; + const currentPageId = this.context.pageContext.listItem?.id || 0; + const currentPageProperties = await this._sp.web.lists + .getByTitle(this.docLibTitle) + .items.getById(currentPageId) + .select( + ...selectedFields.filter((field) => filteredAvailableFields.has(field)) + )(); + for (let i = 0; i < selectedFields.length; i++) { + const field = selectedFields[i]; + const isAvailable = filteredAvailableFields.has(field); + propertyItems.push({ + field, + isAvailable, + label: isAvailable ? (filteredAvailableFields.get(field) || '') : field, + value: currentPageProperties[field], + }); } - + return propertyItems; } protected onDispose(): void { @@ -93,28 +93,30 @@ export default class EnhancedPagePropertiesWebPart extends BaseClientSideWebPart } protected get dataVersion(): Version { - return Version.parse('1.0'); + return Version.parse("1.0"); } protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration { return { pages: [ { - header: { - description: strings.PropertyPaneDescription - }, groups: [ { - groupName: strings.BasicGroupName, groupFields: [ - PropertyPaneTextField('description', { - label: strings.DescriptionFieldLabel - }) - ] - } - ] - } - ] + PropertyPaneTextField("title", { + label: "Title", + }), + PropertyPaneTextField("fields", { + label: "Fields", + description: "separate by comma", + multiline: true, + rows: 5, + }), + ], + }, + ], + }, + ], }; } } diff --git a/samples/react-enhanced-page-properties/src/webparts/enhancedPageProperties/components/EnhancedPageProperties.module.scss b/samples/react-enhanced-page-properties/src/webparts/enhancedPageProperties/components/EnhancedPageProperties.module.scss index 9bd832434..d86e1fa05 100644 --- a/samples/react-enhanced-page-properties/src/webparts/enhancedPageProperties/components/EnhancedPageProperties.module.scss +++ b/samples/react-enhanced-page-properties/src/webparts/enhancedPageProperties/components/EnhancedPageProperties.module.scss @@ -26,7 +26,17 @@ &:hover { background-color: #f0f0f0; } + + &.errorMessage { + background-color: #fce100; + font-style: italic; + } + + &.errorMessage:hover { + background-color: #fce100; + } } + } } } \ No newline at end of file diff --git a/samples/react-enhanced-page-properties/src/webparts/enhancedPageProperties/components/EnhancedPageProperties.tsx b/samples/react-enhanced-page-properties/src/webparts/enhancedPageProperties/components/EnhancedPageProperties.tsx index c635c71bc..4f8a4eef2 100644 --- a/samples/react-enhanced-page-properties/src/webparts/enhancedPageProperties/components/EnhancedPageProperties.tsx +++ b/samples/react-enhanced-page-properties/src/webparts/enhancedPageProperties/components/EnhancedPageProperties.tsx @@ -1,19 +1,28 @@ -import * as React from "react"; -import styles from "./EnhancedPageProperties.module.scss"; +import * as React from 'react'; -export default function EnhancedPageProperties(): JSX.Element { +import styles from './EnhancedPageProperties.module.scss'; +import { IEnhancedPagePropertiesProps } from './IEnhancedPagePropertiesProps'; + +export default function EnhancedPageProperties( + props: IEnhancedPagePropertiesProps +): JSX.Element { return (
-

Site Scope

+

{props.title}

-
-

Function

- COMMUNICAITONS AND STAKEHOLDER -
-
-

Activity

- Advertising and Communications -
+ {props.items.map((item) => ( +
+

{item.label}

+ {item.isAvailable ? ( + {item.value || "-"} + ) : ( + + Field not available in the Library metadata. Please check again the + web part configuration. + + )} +
+ ))}
); diff --git a/samples/react-enhanced-page-properties/src/webparts/enhancedPageProperties/components/IEnhancedPagePropertiesProps.ts b/samples/react-enhanced-page-properties/src/webparts/enhancedPageProperties/components/IEnhancedPagePropertiesProps.ts index de87960c7..adaf0717c 100644 --- a/samples/react-enhanced-page-properties/src/webparts/enhancedPageProperties/components/IEnhancedPagePropertiesProps.ts +++ b/samples/react-enhanced-page-properties/src/webparts/enhancedPageProperties/components/IEnhancedPagePropertiesProps.ts @@ -1,7 +1,6 @@ +import { propertyItem } from "../EnhancedPagePropertiesWebPart"; + export interface IEnhancedPagePropertiesProps { - description: string; - isDarkTheme: boolean; - environmentMessage: string; - hasTeamsContext: boolean; - userDisplayName: string; + title: string; + items: propertyItem[]; }