Add configuration

This commit is contained in:
AriGunawan 2023-07-30 12:34:51 +07:00
parent 9cd8043f94
commit 5ae936e57d
6 changed files with 249 additions and 115 deletions

View File

@ -15,6 +15,7 @@
"@microsoft/sp-office-ui-fabric-core": "1.17.4", "@microsoft/sp-office-ui-fabric-core": "1.17.4",
"@microsoft/sp-property-pane": "1.17.4", "@microsoft/sp-property-pane": "1.17.4",
"@microsoft/sp-webpart-base": "1.17.4", "@microsoft/sp-webpart-base": "1.17.4",
"@pnp/sp": "^3.17.0",
"office-ui-fabric-react": "^7.199.1", "office-ui-fabric-react": "^7.199.1",
"react": "17.0.1", "react": "17.0.1",
"react-dom": "17.0.1", "react-dom": "17.0.1",
@ -8507,6 +8508,70 @@
"node": ">= 8" "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": { "node_modules/@pnpm/crypto.base32-hash": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/@pnpm/crypto.base32-hash/-/crypto.base32-hash-1.0.1.tgz", "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": { "@pnpm/crypto.base32-hash": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/@pnpm/crypto.base32-hash/-/crypto.base32-hash-1.0.1.tgz", "resolved": "https://registry.npmjs.org/@pnpm/crypto.base32-hash/-/crypto.base32-hash-1.0.1.tgz",

View File

@ -13,33 +13,34 @@
"serve": "gulp bundle --custom-serve --max_old_space_size=4096 && fast-serve" "serve": "gulp bundle --custom-serve --max_old_space_size=4096 && fast-serve"
}, },
"dependencies": { "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", "@fluentui/react": "^7.199.1",
"@microsoft/sp-core-library": "1.17.4",
"@microsoft/sp-component-base": "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-property-pane": "1.17.4",
"@microsoft/sp-webpart-base": "1.17.4", "@microsoft/sp-webpart-base": "1.17.4",
"@microsoft/sp-lodash-subset": "1.17.4", "@pnp/sp": "^3.17.0",
"@microsoft/sp-office-ui-fabric-core": "1.17.4" "office-ui-fabric-react": "^7.199.1",
"react": "17.0.1",
"react-dom": "17.0.1",
"tslib": "2.3.1"
}, },
"devDependencies": { "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-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-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", "@types/webpack-env": "~1.15.2",
"ajv": "^6.12.5", "ajv": "^6.12.5",
"eslint": "8.7.0", "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", "eslint-plugin-react-hooks": "4.3.0",
"@microsoft/sp-module-interfaces": "1.17.4", "gulp": "4.0.2",
"spfx-fast-serve-helpers": "~1.17.0" "spfx-fast-serve-helpers": "~1.17.0",
"typescript": "4.5.5"
} }
} }

View File

@ -1,91 +1,91 @@
import * as React from 'react'; import "@pnp/sp/webs";
import * as ReactDom from 'react-dom'; import "@pnp/sp/lists";
import { Version } from '@microsoft/sp-core-library'; 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 { import {
IPropertyPaneConfiguration, IPropertyPaneConfiguration,
PropertyPaneTextField PropertyPaneTextField,
} from '@microsoft/sp-property-pane'; } from "@microsoft/sp-property-pane";
import { BaseClientSideWebPart } from '@microsoft/sp-webpart-base'; import { BaseClientSideWebPart } from "@microsoft/sp-webpart-base";
import { IReadonlyTheme } from '@microsoft/sp-component-base'; import { SPFI, spfi, SPFx } from "@pnp/sp";
import * as strings from 'EnhancedPagePropertiesWebPartStrings'; import EnhancedPageProperties from "./components/EnhancedPageProperties";
import EnhancedPageProperties from './components/EnhancedPageProperties'; import { IEnhancedPagePropertiesProps } from "./components/IEnhancedPagePropertiesProps";
import { IEnhancedPagePropertiesProps } from './components/IEnhancedPagePropertiesProps';
export interface IEnhancedPagePropertiesWebPartProps { 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<IEnhancedPagePropertiesWebPartProps> { export default class EnhancedPagePropertiesWebPart extends BaseClientSideWebPart<IEnhancedPagePropertiesWebPartProps> {
private readonly docLibTitle = 'Site Pages';
private _sp: SPFI;
private _isDarkTheme: boolean = false; public async render(): Promise<void> {
private _environmentMessage: string = ''; const items: propertyItem[] = await this.getCurrentPageProperties();
const element: React.ReactElement<IEnhancedPagePropertiesProps> =
public render(): void { React.createElement(EnhancedPageProperties, {
const element: React.ReactElement<IEnhancedPagePropertiesProps> = React.createElement( title: this.properties.title,
EnhancedPageProperties, items,
{ });
description: this.properties.description,
isDarkTheme: this._isDarkTheme,
environmentMessage: this._environmentMessage,
hasTeamsContext: !!this.context.sdks.microsoftTeams,
userDisplayName: this.context.pageContext.user.displayName
}
);
ReactDom.render(element, this.domElement); ReactDom.render(element, this.domElement);
} }
protected onInit(): Promise<void> { protected async onInit(): Promise<void> {
return this._getEnvironmentMessage().then(message => { await super.onInit();
this._environmentMessage = message; this._sp = spfi().using(SPFx(this.context));
}
protected convertSelectedFieldsString(): string[] {
return this.properties.fields.split(",").map((field) => field.trim());
}
protected async getCurrentPageProperties(): Promise<propertyItem[]> {
// 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<string, string> = new Map();
for (let i = 0; i < availableFields.length; i++) {
const field = availableFields[i];
if (field.Hidden) continue;
filteredAvailableFields.set(field.InternalName, field.Title);
}
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;
private _getEnvironmentMessage(): Promise<string> {
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 onThemeChanged(currentTheme: IReadonlyTheme | undefined): void {
if (!currentTheme) {
return;
}
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);
}
} }
protected onDispose(): void { protected onDispose(): void {
@ -93,28 +93,30 @@ export default class EnhancedPagePropertiesWebPart extends BaseClientSideWebPart
} }
protected get dataVersion(): Version { protected get dataVersion(): Version {
return Version.parse('1.0'); return Version.parse("1.0");
} }
protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration { protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration {
return { return {
pages: [ pages: [
{ {
header: {
description: strings.PropertyPaneDescription
},
groups: [ groups: [
{ {
groupName: strings.BasicGroupName,
groupFields: [ groupFields: [
PropertyPaneTextField('description', { PropertyPaneTextField("title", {
label: strings.DescriptionFieldLabel label: "Title",
}) }),
] PropertyPaneTextField("fields", {
} label: "Fields",
] description: "separate by comma",
} multiline: true,
] rows: 5,
}),
],
},
],
},
],
}; };
} }
} }

View File

@ -26,7 +26,17 @@
&:hover { &:hover {
background-color: #f0f0f0; background-color: #f0f0f0;
} }
&.errorMessage {
background-color: #fce100;
font-style: italic;
} }
&.errorMessage:hover {
background-color: #fce100;
}
}
} }
} }
} }

View File

@ -1,19 +1,28 @@
import * as React from "react"; import * as React from 'react';
import styles from "./EnhancedPageProperties.module.scss";
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 ( return (
<section className={styles.enhancedPageProperties}> <section className={styles.enhancedPageProperties}>
<h2>Site Scope</h2> <h2>{props.title}</h2>
<div className={styles.content}> <div className={styles.content}>
<div className={styles.item}> {props.items.map((item) => (
<h3>Function</h3> <div key={item.field} className={styles.item}>
<span>COMMUNICAITONS AND STAKEHOLDER</span> <h3>{item.label}</h3>
</div> {item.isAvailable ? (
<div className={styles.item}> <span>{item.value || "-"}</span>
<h3>Activity</h3> ) : (
<span>Advertising and Communications</span> <span className={styles.errorMessage}>
Field not available in the Library metadata. Please check again the
web part configuration.
</span>
)}
</div> </div>
))}
</div> </div>
</section> </section>
); );

View File

@ -1,7 +1,6 @@
import { propertyItem } from "../EnhancedPagePropertiesWebPart";
export interface IEnhancedPagePropertiesProps { export interface IEnhancedPagePropertiesProps {
description: string; title: string;
isDarkTheme: boolean; items: propertyItem[];
environmentMessage: string;
hasTeamsContext: boolean;
userDisplayName: string;
} }