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-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",

View File

@ -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"
}
}

View File

@ -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<IEnhancedPagePropertiesWebPartProps> {
private readonly docLibTitle = 'Site Pages';
private _sp: SPFI;
private _isDarkTheme: boolean = false;
private _environmentMessage: string = '';
public render(): void {
const element: React.ReactElement<IEnhancedPagePropertiesProps> = 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<void> {
const items: propertyItem[] = await this.getCurrentPageProperties();
const element: React.ReactElement<IEnhancedPagePropertiesProps> =
React.createElement(EnhancedPageProperties, {
title: this.properties.title,
items,
});
ReactDom.render(element, this.domElement);
}
protected onInit(): Promise<void> {
return this._getEnvironmentMessage().then(message => {
this._environmentMessage = message;
});
protected async onInit(): Promise<void> {
await super.onInit();
this._sp = spfi().using(SPFx(this.context));
}
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 convertSelectedFieldsString(): string[] {
return this.properties.fields.split(",").map((field) => field.trim());
}
protected onThemeChanged(currentTheme: IReadonlyTheme | undefined): void {
if (!currentTheme) {
return;
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);
}
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,
}),
],
},
],
},
],
};
}
}

View File

@ -26,7 +26,17 @@
&:hover {
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 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 (
<section className={styles.enhancedPageProperties}>
<h2>Site Scope</h2>
<h2>{props.title}</h2>
<div className={styles.content}>
<div className={styles.item}>
<h3>Function</h3>
<span>COMMUNICAITONS AND STAKEHOLDER</span>
</div>
<div className={styles.item}>
<h3>Activity</h3>
<span>Advertising and Communications</span>
</div>
{props.items.map((item) => (
<div key={item.field} className={styles.item}>
<h3>{item.label}</h3>
{item.isAvailable ? (
<span>{item.value || "-"}</span>
) : (
<span className={styles.errorMessage}>
Field not available in the Library metadata. Please check again the
web part configuration.
</span>
)}
</div>
))}
</div>
</section>
);

View File

@ -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[];
}