Fixed readme, linting, typos, sample manifest, removed upgrade files, updated devcontainer

This commit is contained in:
Hugo Bernier 2024-03-16 13:57:07 -04:00
parent 56ba043f2c
commit 6cafec44de
27 changed files with 335 additions and 3630 deletions

View File

@ -1,15 +1,14 @@
// 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.0.0",
"image": "docker.io/m365pnp/spfx:ga",
// Set *default* container specific settings.json values on container create.
"settings": {},
// Add the IDs of extensions you want installed when the container is created.
"name": "SPFx 1.17.1",
"image": "docker.io/m365pnp/spfx:1.17.1",
"customizations": {
"vscode": {
"extensions": [
"editorconfig.editorconfig",
"dbaeumer.vscode-eslint"
],
// Use 'forwardPorts' to make a list of ports inside the container available locally.
]
}
},
"forwardPorts": [
4321,
35729,

View File

@ -7,9 +7,11 @@ 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
cp ~/.gcb-serve-data/gcb-serve.cer ./spfx-dev-cert.cer
cp ~/.gcb-serve-data/gcb-serve.cer ./spfx-dev-cert.pem
# 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

View File

@ -0,0 +1 @@
v16.20.0

View File

@ -1,9 +1,9 @@
# Property Bag Navigation Webparts
# Property Bag Navigation Web parts
## Summary
A set of webparts that lets you set property bag settings on site collections and enable navigation using those properties.
[picture of the web part in action]
A set of web parts that lets you set property bag settings on site collections and enable navigation using those properties.
![PropertyBagEditorDisplay](./assets/PropertyBagEditorDisplay.PNG)
## Compatibility
@ -26,8 +26,6 @@ A set of webparts that lets you set property bag settings on site collections an
* [SharePoint Framework](https://blogs.office.com/2017/02/23/sharepoint-framework-reaches-general-availability-build-and-deploy-engaging-web-parts-today/)
* [Microsoft 365 tenant](https://learn.microsoft.com/sharepoint/dev/spfx/set-up-your-development-environment)
## Prerequisites
> pnp-js-core
@ -43,52 +41,53 @@ Version|Date|Comments
1.0|march 19, 2017|Initial release
2.0|Feb 21, 2024|Upgraded to SPFX 1.17.1
## Minimal Path to Awesome
- Clone this repository
- This project uses the JSOM to interact with the property bag. Therefore in config/config.js you need to change the paths
on the externals sp-init,microsoft-ajax,sp-runtime, and sharepoint to point to your tenant.
- in the command line run:
- `npm install`
- `gulp serve`
* Clone this repository
* This project uses the JSOM to interact with the property bag. Therefore in config/config.js you need to change the paths
on the externals `sp-init`,`microsoft-ajax`,`sp-runtime`, and SharePoint to point to your tenant.
* in the command line run:
* `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.
> 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.
> Note that using the JSOM to updates the propertybag of a site is not supported on 'NoScript' sites. You can enable scripts on all sites using the admnin center or via powershell:
Set-PnPTenantSite -Identity {SiteUrl} -DenyAddAndCustomizePages:$false
> Note that using the JSOM to updates the property bag of a site is not supported on 'NoScript' sites. You can enable scripts on all sites using the admin center or via PowerShell:
>
> ```powershell
> Set-PnPTenantSite -Identity {SiteUrl} -DenyAddAndCustomizePages:$false
> ```
## Features
This project consists of two webparts that can be used to manage the Property Bags for SharePoint sites and two webparts that can be used to display navigational components from those Properties.
- PropertyBagEditor
This project consists of two web parts that can be used to manage the Property Bags for SharePoint sites and two web parts that can be used to display navigational components from those Properties.
* PropertyBagEditor
This web part allows a site owner/administrator to edit selected items in a site&#39;s Property Bag. It edits the properties of the current site. A sample display is shown below:
![PropertyBagEditorDisplay](./src/images/PropertyBagEditorDisplay.PNG)
![PropertyBagEditorDisplay](./assets/PropertyBagEditorDisplay.PNG)
Selecting a Property and clicking the Edit button will bring up the Edit Panel:
![PropertyBagEditorEdur](./src/images/PropertyBagEditorEdit.PNG)
![PropertyBagEditorEdur](./assets/PropertyBagEditorEdit.PNG)
Here you can change the value of the property and specify if the property should be included in the search Index.
The Properties that can be edited are specified in the web part&#39;s Property Pane:
![PropertyBagEditorEdur](./src/images/PropertyBagEditorConfig.PNG)
![PropertyBagEditorEdur](./assets/PropertyBagEditorConfig.PNG)
The Properties set in the Property Pane of this web part are crawled properties, and should be mapped to managed properties so that can be used by the other webparts in this project.
The Properties set in the Property Pane of this web part are crawled properties, and should be mapped to managed properties so that can be used by the other web parts in this project.
The Site whose properties are to be edited can be passed in via a query parameter. While this web part can be added to any page, it would be most useful if added to a page in an infrastructure site collection in the tenant, and then linked to from all other sites via a link in the Site Settings page.
The following script shows how to add such a link to all sites &#39;Site Settings&#39; page using PNP Powershell. It will add a menu item named &#39;Edit Site Metadata &#39; to the Site Settings of each Team Site that links to the PropertBagEdcitor.aspx page on the tenants infrastructure site (this site is named 'cdn' in the example below).
The following script shows how to add such a link to all sites &#39;Site Settings&#39; page using PNP PowerShell. It will add a menu item named &#39;Edit Site Metadata &#39; to the Site Settings of each Team Site that links to the PropertyBagEditor.aspx page on the tenants infrastructure site (this site is named 'cdn' in the example below).
```
```powershell
$adminSiteUrl=&quot;https://tenant-admin.sharepoint.com&quot;
$customActionDescription=&quot;CUSTOM_\ ___Navigation__ \__Metadata&quot;
$pageUrl=&quot;https://tenant.sharepoint.com/sites/cdn/SitePages/PropertBagEdcitor.aspx?siteUrl={0}&quot;
$pageUrl=&quot;https://tenant.sharepoint.com/sites/cdn/SitePages/PropertyBagEditor.aspx?siteUrl={0}&quot;
$credentials=get-credential
@ -126,49 +125,47 @@ foreach($site in $sites){
}
```
- PropertyBagDisplay
* PropertyBagDisplay
The propertyBagDisplay web part can be used by an administrator to view and edit selected properties across sites in the tenant:
![PropertyBagDisplay](./src/images/PropertyBagDisplayDisplay.PNG)
![PropertyBagDisplay](./assets/PropertyBagDisplayDisplay.PNG)
In the Property Pane, an administrator must specify both the Crawled Property Name and the Managed Property name (separated by a pipe character) of the properties to be included in the web part:
![PropertyBagDisplayConfig](./src/images/PropertBagDisplayConfig.PNG)
![PropertyBagDisplayConfig](./assets/PropertBagDisplayConfig.PNG)
The administrator can also include a list of site templates to narrow down the list of sites to be included in the web part. When specifying site templates to include you can include just the Site Template Name (STS) and all sites within that template name will be included, or you can specify the Site Template Name and ID, separated by a &#39;#&quot; character (STS#1) to have only sites with that template name and ID included.
The web part displays the site template, Title and Url, plus the selected Managed Properties for all sites in the tenant with the selected site template. The Managed Properties are only displayed if they have been set as searchable, and a full crawl has been run. After selecting a Site, a user can click the edit button to edit the Crawled properties (i.e. the raw property bag values) for the selected site:
The web part displays the site template, Title and URL, plus the selected Managed Properties for all sites in the tenant with the selected site template. The Managed Properties are only displayed if they have been set as searchable, and a full crawl has been run. After selecting a Site, a user can click the edit button to edit the Crawled properties (i.e. the raw property bag values) for the selected site:
![PropertyBagDisplayEdit](./src/images/PropertyBagDisplayEdit.PNG)
![PropertyBagDisplayEdit](./assets/PropertyBagDisplayEdit.PNG)
On the edit panel one can specify a new value for each property as well as whether that property is to be included in the search index. Additionally one can specify that a full crawl of the site should be run once the properties are saved.
- PropertyBagFilteredSiteList
* PropertyBagFilteredSiteList
This web part displays a list of all sites that meet the criteria specified in the property pane by the administrator:
![PropertyBagFilteredSiteListDisplay](./src/images/PropertyBagFilteredSiteListDisplay.PNG)
![PropertyBagFilteredSiteListDisplay](./assets/PropertyBagFilteredSiteListDisplay.PNG)
Additionally, it lets the user narrow down the list of sites displayed by applying metadata filters that are set up by the administrator in the Property Pane( Business Unit and Continent in the example above):
![PropertyBagFilteredSiteListConfig](./src/images/PropertyBagFilteredSiteListConfigy.PNG)
![PropertyBagFilteredSiteListConfig](./assets/PropertyBagFilteredSiteListConfigy.PNG)
In the PropertyPane above, the 'Site Templates to Include' and 'Metadata Filters' are used to filter which site collections are retrieved from search. The 'User Filters' are used to allow the user to easily filter the results returned from search using the command bar on the top of the display.
- PropertyBagGlobalNav
* PropertyBagGlobalNav
This Web part builds a navigation menu based on the Managed Properties set up in the PropertyPane:
![propertyBagGlobalNavDisplay](./src/images/propertyBagGlobalNavDisplay.PNG)
![propertyBagGlobalNavDisplay](./assets/propertyBagGlobalNavDisplay.PNG)
In the PropertyPane, an administrator just needs to specify which Managed Properties are to be used to build the Navigation menu:
![PropertyBagGlobalNavConfig](./src/images/PropertyBagGlobalNavConfig.PNG)
![PropertyBagGlobalNavConfig](./assets/PropertyBagGlobalNavConfig.PNG)
If desired, the admin can also specify which site templates should be included in the menu, as wall as any additional filters. Additional Filters can be specified in the format 'ManagedPropertyName=value';
## 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://m365-visitor-stats.azurewebsites.net/sp-dev-fx-webparts/samples/react-property-bag-editor" />

View File

Before

Width:  |  Height:  |  Size: 8.1 KiB

After

Width:  |  Height:  |  Size: 8.1 KiB

View File

@ -2,14 +2,14 @@
{
"name": "pnp-sp-dev-spfx-web-parts-react-property-bag-editor",
"source": "pnp",
"title": "Property Bag Navigation Webparts",
"shortDescription": "A set of webparts that lets you set property bag settings on site collections and enable navigation using those properties.",
"title": "Property Bag Navigation Web parts",
"shortDescription": "A set of web parts that lets you set property bag settings on site collections and enable navigation using those properties.",
"url": "https://github.com/pnp/sp-dev-fx-webparts/tree/main/samples/react-property-bag-editor",
"longDescription": [
"A set of webparts that lets you set property bag settings on site collections and enable navigation using those properties."
"A set of web parts that lets you set property bag settings on site collections and enable navigation using those properties."
],
"creationDateTime": "2017-03-19",
"updateDateTime": "2017-03-19",
"updateDateTime": "2024-02-21",
"products": [
"SharePoint"
],
@ -27,14 +27,13 @@
{
"type": "image",
"order": 100,
"url": "https://github.com/pnp/sp-dev-fx-webparts/raw/main/samples/react-property-bag-editor/src/images/PropertyBagEditorDisplay.PNG",
"alt": "Property Bag Navigation Webparts"
"url": "https://github.com/pnp/sp-dev-fx-webparts/raw/main/samples/react-property-bag-editor/assets/PropertyBagEditorDisplay.PNG",
"alt": "Property Bag Navigation Web parts"
}
],
"authors": [
{
"gitHubAccount": "russgove",
"company": "",
"pictureUrl": "https://github.com/russgove.png",
"name": "Russell Gove"
}

View File

@ -32,6 +32,7 @@ export default class PropertyBagDisplayWebPart extends BaseClientSideWebPart<IPr
}
);
// eslint-disable-next-line @microsoft/spfx/pair-react-dom-render-unmount
ReactDom.render(element, this.domElement);
}
public onInit(): Promise<void> {

View File

@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/explicit-function-return-type */
import * as _ from "lodash";
import * as React from "react";
import pnp, { SearchQuery, SearchResults, Web } from "sp-pnp-js";
@ -23,9 +24,10 @@ import {
} from "office-ui-fabric-react/lib/Panel";
export interface IPropertyBagDisplayState {
selectedIndex: number; // the currently selected site
managedToCrawedMapping?: Array<ManagedToCrawledMappingEntry>;// Determines which Carwled propeties are mapped to which Managed Properties
managedToCrawedMapping?: Array<ManagedToCrawledMappingEntry>;// Determines which Crawled properties are mapped to which Managed Properties
errorMessages: Array<md.Message>; // a list of error massages displayed on the page
isediting?: boolean; //Determines if the edit panel is displayed
// eslint-disable-next-line @typescript-eslint/no-explicit-any
sites: Array<any>; // the list of sites displayed in the component
workingStorage?: DisplaySite;// A working copy of the site being edited
managedPropNames?: Array<string>; // the list of managed properties to be displayed
@ -171,8 +173,8 @@ export default class PropertyBagDisplay extends React.Component<IPropertyBagDisp
/**
* Removes a message from the MessageDIsplay when the user click the 'x'
*
* @param {Array<md.Message>} messageList The list to remove the masseg from (the 'main' window of the Panel)
* @param {string} messageId The Id of the massge to remove
* @param {Array<md.Message>} messageList The list to remove the message from (the 'main' window of the Panel)
* @param {string} messageId The Id of the message to remove
*
* @memberOf PropertyBagDisplay
*/
@ -183,7 +185,7 @@ export default class PropertyBagDisplay extends React.Component<IPropertyBagDisp
this.setState((current) => ({ ...current, errorMessages: messageList }));
}
/**
* Removes a massage from the main windo
* Removes a massage from the main window
*
* @param {string} messageId
*
@ -212,9 +214,10 @@ export default class PropertyBagDisplay extends React.Component<IPropertyBagDisp
*
* @memberOf PropertyBagDisplay
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
private changeSearchable(siteUrl: string, propname: string, newValue: boolean): Promise<any> {
if (newValue) {//make prop searchable
if (_.indexOf(this.state.workingStorage.searchableProps, propname) === -1) {// wasa not searchable, mpw it is
if (_.indexOf(this.state.workingStorage.searchableProps, propname) === -1) {// was not searchable, now it is
console.log(propname + "was not searchable, now it is ");
this.state.workingStorage.searchableProps.push(propname);
return utils.saveSearchablePropertiesToSharePoint(siteUrl, this.state.workingStorage.searchableProps);
@ -224,8 +227,8 @@ export default class PropertyBagDisplay extends React.Component<IPropertyBagDisp
return Promise.resolve();
}
}
else { // make prop not searchablke
if (_.indexOf(this.state.workingStorage.searchableProps, propname) !== -1) {// wasa not searchable, mpw it is
else { // make prop not searchable
if (_.indexOf(this.state.workingStorage.searchableProps, propname) !== -1) {// was not searchable, now it is
console.log(propname + "was searchable, now it is not");
_.remove(this.state.workingStorage.searchableProps, p => { return p === propname; });
return utils.saveSearchablePropertiesToSharePoint(siteUrl, this.state.workingStorage.searchableProps);
@ -250,7 +253,7 @@ export default class PropertyBagDisplay extends React.Component<IPropertyBagDisp
}));
}
/**
* Caled by the Details list to render a column as a URL rather than text
* Called by the Details list to render a column as a URL rather than text
*
* @private
* @param {*} [item]
@ -260,6 +263,7 @@ export default class PropertyBagDisplay extends React.Component<IPropertyBagDisp
*
* @memberOf PropertyBagDisplay
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
private renderSiteUrl(item?: any, index?: number, column?: IColumn): JSX.Element {
return (<a href={item[column.fieldName]}>{item[column.fieldName]} </a>);
}
@ -268,7 +272,7 @@ export default class PropertyBagDisplay extends React.Component<IPropertyBagDisp
/**
* Sets the columns to be displayed in the list.
* These are SiteTemplate, Title and Url, plus any properties specified in
* the propertypane
* the property pane
*
* @private
* @returns {Array<IColumn>}
@ -321,15 +325,15 @@ export default class PropertyBagDisplay extends React.Component<IPropertyBagDisp
}
/** react lifecycle */
/**
* Called when the componet loads.
* Builds the query to search sharepoint for the list of sites to display and formates
* Called when the component loads.
* Builds the query to search sharepoint for the list of sites to display and formats
* the results to be displayed in the list
*
*
* @memberOf PropertyBagDisplay
*/
public componentDidMount(): void {
let initState = {
const initState = {
columns: this.setupColumns(),
managedToCrawedMapping: [],
@ -338,7 +342,7 @@ export default class PropertyBagDisplay extends React.Component<IPropertyBagDisp
errorMessages: []
};
for (const prop of this.props.propertiesToDisplay) {
const names: Array<string> = prop.split('|');// crawledpropety/managed property
const names: Array<string> = prop.split('|');// crawled property/managed property
initState.managedToCrawedMapping.push(new ManagedToCrawledMappingEntry(names[0], names[1]));
initState.managedPropNames.push(names[1]);
}
@ -372,6 +376,7 @@ export default class PropertyBagDisplay extends React.Component<IPropertyBagDisp
};
pnp.sp.search(q).then((results: SearchResults) => {
for (const r of results.PrimarySearchResults) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const obj: any = {};
for (const dp of initState.managedPropNames) {
obj[dp] = r[dp];
@ -396,6 +401,7 @@ export default class PropertyBagDisplay extends React.Component<IPropertyBagDisp
*
* @memberOf PropertyBagDisplay
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
private onActiveItemChanged(item?: any, index?: number): void {
this.setState((current) => ({ ...current, selectedIndex: index }));
}
@ -408,6 +414,7 @@ export default class PropertyBagDisplay extends React.Component<IPropertyBagDisp
* @memberOf PropertyBagDisplay
*/
private onSave(e?: MouseEvent): void {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const promises: Array<Promise<any>> = [];
for (const prop of this.state.workingStorage.DisplayProps) {
const promise = utils.setSPProperty(prop.crawledPropertyName, prop.value, this.state.workingStorage.Url)
@ -417,8 +424,10 @@ export default class PropertyBagDisplay extends React.Component<IPropertyBagDisp
promises.push(promise);
}
Promise.all(promises)
// eslint-disable-next-line @typescript-eslint/no-explicit-any
.then((results: Array<any>) => {
if (this.state.workingStorage.forceCrawl) {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
utils.forceCrawl(this.state.workingStorage.Url);
}
debugger;
@ -463,7 +472,7 @@ export default class PropertyBagDisplay extends React.Component<IPropertyBagDisp
/**
* Called when user wishes to edit an item.
* The List displayes the values from the search index.
* The List displays the values from the search index.
* This method gets the values from the actual PropertyBag so that they can be edited.
*
* @param {MouseEvent} [e]
@ -476,11 +485,13 @@ export default class PropertyBagDisplay extends React.Component<IPropertyBagDisp
const selectedSite = this.state.sites[this.state.selectedIndex];
const web = new Web(selectedSite.Url);
// let context = this;
// eslint-disable-next-line @typescript-eslint/no-floating-promises
web.select("Title", "AllProperties").expand("AllProperties").get().then((r) => {
const crawledProps: Array<string> = this.props.propertiesToDisplay.map(item => {
return item.split("|")[0];
});
let temp = _.clone(selectedSite);
const temp = _.clone(selectedSite);
// eslint-disable-next-line dot-notation
temp.searchableProps = utils.decodeSearchableProps(r.AllProperties["vti_x005f_indexedpropertykeys"]);
temp.DisplayProps = utils.SelectProperties(r.AllProperties, crawledProps, temp.searchableProps);
temp.errorMessages = new Array<md.Message>();
@ -506,6 +517,7 @@ export default class PropertyBagDisplay extends React.Component<IPropertyBagDisp
*
* @memberOf PropertyBagDisplay
*/
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type, @typescript-eslint/no-explicit-any
private _onColumnClick(event: any, column: IColumn) {
column = _.find(this.state.columns, c => c.fieldName === column.fieldName);// find the object in state
// If we've sorted this column, flip it.
@ -517,7 +529,7 @@ export default class PropertyBagDisplay extends React.Component<IPropertyBagDisp
column.isSortedDescending = false;
}
// Sort the items.
let temp = _.orderBy(this.state.sites, (site) => {
const temp = _.orderBy(this.state.sites, (site) => {
if (site[column.fieldName]) {
return site[column.fieldName].toLowerCase();
}
@ -558,8 +570,7 @@ export default class PropertyBagDisplay extends React.Component<IPropertyBagDisp
checkboxVisibility={CheckboxVisibility.hidden}
onActiveItemChanged={this.onActiveItemChanged.bind(this)
}
>
</DetailsList>
/>
{this.renderPopup.bind(this)()}
</div >
);

View File

@ -46,6 +46,7 @@ export default class PropertyBagEditorWebPart extends BaseClientSideWebPart<IPro
props
);
// eslint-disable-next-line @microsoft/spfx/pair-react-dom-render-unmount
ReactDom.render(element, this.domElement);
}

View File

@ -1,3 +1,5 @@
/* eslint-disable react/no-deprecated */
/* eslint-disable @typescript-eslint/explicit-function-return-type */
import * as _ from "lodash";
import { DefaultButton, PrimaryButton } from "office-ui-fabric-react/lib/Button";
import { CommandBar } from "office-ui-fabric-react/lib/CommandBar";
@ -31,6 +33,7 @@ export interface IPropertyBagEditorState {
export default class PropertyBagEditor extends React.Component<IPropertyBagEditorProps, IPropertyBagEditorState> {
public refs: {
[key: string]: React.ReactInstance;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
list: any //DetailsList
};
public constructor(props: IPropertyBagEditorProps) {
@ -58,7 +61,7 @@ export default class PropertyBagEditor extends React.Component<IPropertyBagEdito
onClick: this.onEditItemClicked.bind(this),
icon: "Edit"
}];
};
}
/**
* Determines if an item is selected.
@ -69,13 +72,14 @@ export default class PropertyBagEditor extends React.Component<IPropertyBagEdito
*/
get ItemIsSelected(): boolean {
if (!this.state) { return false; }
return (this.state.selectedIndex != -1);
return (this.state.selectedIndex !== -1);
}
/** react lifecycle */
public componentWillMount() {
const web = new Web(this.props.siteUrl);
// eslint-disable-next-line @typescript-eslint/no-floating-promises
web.select("Title", "AllProperties").expand("AllProperties").get().then(r => {
debugger;
const sp = utils.decodeSearchableProps(r.AllProperties.vti_x005f_indexedpropertykeys);
@ -84,11 +88,12 @@ export default class PropertyBagEditor extends React.Component<IPropertyBagEdito
});
}
/** event hadlers */
/** event handlers */
private stopediting() {
this.setState((current) => ({ ...current, isediting: false }))
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
private onActiveItemChanged(item?: any, index?: number) {
this.setState((current) => ({ ...current, selectedIndex: index }))
}
@ -143,8 +148,10 @@ export default class PropertyBagEditor extends React.Component<IPropertyBagEdito
*/
private onSave(e?: MouseEvent): void {
debugger;
// eslint-disable-next-line @typescript-eslint/no-floating-promises
utils.setSPProperty(this.state.workingStorage.crawledPropertyName, this.state.workingStorage.value, this.props.siteUrl)
.then(value => {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
this.changeSearchable(this.state.workingStorage.crawledPropertyName, this.state.workingStorage.searchable)
.then(s => {
const temp = _.clone(this.state.displayProps);// this.state.workingStorage = null;
@ -174,6 +181,7 @@ export default class PropertyBagEditor extends React.Component<IPropertyBagEdito
*
* @memberOf PropertyBagEditor
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
private changeSearchable(propname: string, newValue: boolean): Promise<any> {
if (newValue) {//make prop searchable
if (_.indexOf(this.state.searchableProps, propname) === -1) {// wasa not searchable, mpw it is
@ -199,6 +207,7 @@ export default class PropertyBagEditor extends React.Component<IPropertyBagEdito
}
}
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
private RenderBoolean(item?: any, index?: number, column?: IColumn): any {
if (item[column.fieldName]) {
return (<div>Yes</div>);
@ -229,8 +238,7 @@ export default class PropertyBagEditor extends React.Component<IPropertyBagEdito
checkboxVisibility={CheckboxVisibility.hidden}
items={this.state.displayProps}
onActiveItemChanged={this.onActiveItemChanged.bind(this)}
>
</DetailsList>
/>
<Dialog
hidden={!this.state.isediting} type={DialogType.close}
onDismiss={this.stopediting.bind(this)}

View File

@ -39,6 +39,7 @@ export default class PropertyBagFilteredSiteListWebPart extends BaseClientSideWe
showQueryText: this.properties.showQueryText
}
);
// eslint-disable-next-line @microsoft/spfx/pair-react-dom-render-unmount
ReactDom.render(element, this.domElement);
}

View File

@ -1,3 +1,4 @@
/* eslint-disable dot-notation */
import * as _ from "lodash";
import * as React from "react";
import pnp, { SearchQuery, SearchResults } from "sp-pnp-js";
@ -168,9 +169,9 @@ export default class PropertyBagFilteredSiteList extends React.Component<IProper
};
pnp.sp.search(q).then((results: SearchResults) => {
let sites = [];
const sites = [];
debugger;
let userFilters: UserFilter[] = [];
const userFilters: UserFilter[] = [];
for (const userFilterName of this.props.userFilters) {
userFilters.push(new UserFilter(userFilterName));
}
@ -185,11 +186,11 @@ export default class PropertyBagFilteredSiteList extends React.Component<IProper
this.extractUserFilterValues(userFilters, r);
}
debugger;
let filteredSites = this.filterSites([], sites);// need to pass sites iun here and return the filtered array!!!
const filteredSites = this.filterSites([], sites);// need to pass sites iun here and return the filtered array!!!
this.setState((current) => ({ ...current, filteredSites: filteredSites, sites: sites, userFilters: userFilters }));
}).catch(err => {
debugger;
let errorMessages = this.state.errorMessages;
const errorMessages = this.state.errorMessages;
errorMessages.push(new md.Message(err));
this.setState((current => ({ ...current, errorMessages: errorMessages })));
});
@ -208,7 +209,7 @@ export default class PropertyBagFilteredSiteList extends React.Component<IProper
/**
* Called by the Render method.
* Displayes the Site Description if requested in the PropertyPane.
* Displays the Site Description if requested in the PropertyPane.
* Otherwise displays an empty Div
*
* @param {Site} site
@ -337,12 +338,13 @@ export default class PropertyBagFilteredSiteList extends React.Component<IProper
* Applies the new Filters.
* re-deiplays the list
*
* @param {React.MouseEvent<HTMLElement>} [ev]
* @param {React.MouseEvent<HTMLElement>} [_ev]
* @param {IContextualMenuItem} [item]
*
* @memberOf PropertyBagFilteredSiteList
*/
private filterOnMetadata(ev?: React.MouseEvent<HTMLElement>, item?: IContextualMenuItem) {
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
private filterOnMetadata(_ev?: React.MouseEvent<HTMLElement>, item?: IContextualMenuItem) {
const newFilters = this.ToggleAppliedUserFilter(this.state.appliedUserFilters, item);
this.setState((current) => ({ ...current, appliedUserFilters: newFilters, filteredSites: this.filterSites(newFilters, current.sites) }));
}
@ -358,7 +360,8 @@ export default class PropertyBagFilteredSiteList extends React.Component<IProper
debugger;
const listItems = this.state.filteredSites.map((site) =>
<li >
// eslint-disable-next-line react/jsx-key
<li>
<a href={site.url} target={this.props.linkTarget}>{site.title} --{site["AreaName"]} --{site["Continent"]} </a>
{this.conditionallyRenderDescription(site)}
</li>

View File

@ -22,6 +22,7 @@ export default class PropertyBagGlobalNavWebPart extends BaseClientSideWebPart<I
}
);
// eslint-disable-next-line @microsoft/spfx/pair-react-dom-render-unmount
ReactDom.render(element, this.domElement);
}

View File

@ -25,6 +25,7 @@ export default class PropertyBagGlobalNav extends React.Component<IPropertyBagGl
*
* @memberOf PropertyBagGlobalNav
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
private addMenuItem(items: Array<IContextualMenuItem>, r: any): Array<IContextualMenuItem> {
let currentItem: IContextualMenuItem;
let currentSet: Array<IContextualMenuItem> = items;
@ -90,7 +91,7 @@ export default class PropertyBagGlobalNav extends React.Component<IPropertyBagGl
};
pnp.sp.search(q).then((results: SearchResults) => {
let menuitems = [];
const menuitems = [];
for (const r of results.PrimarySearchResults) {
this.addMenuItem(menuitems, r);
}

View File

@ -29,6 +29,7 @@ export interface IMessageDisplayProps {
* @class MessageDisplay
* @extends {React.Component<IMessageDisplayProps, any>}
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export default class MessageDisplay extends React.Component<IMessageDisplayProps, any> {
/**
*
@ -36,6 +37,7 @@ export default class MessageDisplay extends React.Component<IMessageDisplayProps
*
* @memberOf MessageDisplay
*/
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
public createDismissHandler = (messageId) => (vale) => {
this.props.hideMessage(messageId);
}

View File

@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import * as _ from "lodash";
import { Web } from "sp-pnp-js";
require("sp-init");
@ -7,7 +8,7 @@ require("sharepoint");
import DisplayProp from "./DisplayProp";
/**
* Various utilitty functions used by the React-ProprtyBag* Webparts
* Various utility functions used by the React-PropertyBag* Web parts
*
* @export
* @class utils
@ -27,7 +28,7 @@ export default class utils {
* @memberOf utils
*/
public static EncodePropertyKey(propKey): string {
let bytes = [];
const bytes = [];
for (let i = 0; i < propKey.length; ++i) {
bytes.push(propKey.charCodeAt(i));
bytes.push(0);
@ -74,9 +75,9 @@ export default class utils {
return searchableprops;
}
/**
* AllProperties- the resullsts from web.select("Title", "AllProperties").expand("AllProperties").get()
* propertiesToSelect- The properties you waant to select out of AllProperties
* searchableProperties-- and araay of properties which are known to be searchjable
* AllProperties- the results from web.select("Title", "AllProperties").expand("AllProperties").get()
* propertiesToSelect- The properties you want to select out of AllProperties
* searchableProperties-- and array of properties which are known to be searchable
*
*/
/**
@ -85,7 +86,7 @@ export default class utils {
* @static
* @param {*} AllProperties
* @param {Array<string>} propertiesToSelect The Properties to Select from AllProperties
* @param {Array<string>} searchableProperties An Array of Searchable Properties. These will be marked as seartchable in the results
* @param {Array<string>} searchableProperties An Array of Searchable Properties. These will be marked as searchable in the results
* @param {boolean} [addMissingProps] Indicates if the method should add a empty property if it is in propertiesToSelect but not in AllProperties
* @returns {Array<DisplayProp>}
*

File diff suppressed because it is too large Load Diff

View File

@ -1,197 +0,0 @@
SPFX PROJECT UPGRADE
====================
Upgrades SharePoint Framework project to the specified version
USAGE
m365 spfx project upgrade [options]
OPTIONS
-v, --toVersion [toVersion]
The version of SharePoint Framework to which upgrade the project
--packageManager [packageManager]
The package manager you use. Supported managers npm,pnpm,yarn. Default npm
--shell [shell]
The shell you use. Supported shells bash,powershell,cmd. Default bash
--preview
Upgrade project to the latest SPFx preview version
-f, --outputFile [outputFile]
Path to the file where the upgrade report should be stored in. Ignored when output is tour
-h, --help [help]
Output usage information. Optionally, specify which section of command's help you want to see. Allowed values are options, examples, remarks, response, full. Default is full.
--query [query]
JMESPath query string. See http://jmespath.org/ for more information and examples
-o, --output [output]
Output type. json,text,csv,md. Default json
--verbose
Runs command with verbose logging
--debug
Runs command with debug logging
REMARKS
The spfx project upgrade command helps you upgrade your SharePoint Framework project to the specified version. If no version is specified, the command will upgrade to the latest version of the SharePoint Framework it supports (v1.17.2).
This command doesn't change your project files. Instead, it gives you a report with all steps necessary to upgrade your project to the specified version of the SharePoint Framework. Changing project files is error-prone, especially when it comes to updating your solution's code. This is why at this moment, this command produces a report that you can use yourself to perform the necessary updates and verify that everything is working as expected.
!!! important
Run this command in the folder where the project that you want to upgrade is located. This command doesn't change your project files.
EXAMPLES
Get instructions to upgrade the current SharePoint Framework project to SharePoint Framework version 1.5.0 and save the findings in a Markdown file
m365 spfx project upgrade --toVersion 1.5.0 --output md > "upgrade-report.md"
Get instructions to upgrade the current SharePoint Framework project to SharePoint Framework version 1.5.0 and show the summary of the findings in the shell
m365 spfx project upgrade --toVersion 1.5.0 --output text
Get instructions to upgrade the current SharePoint Framework project to the latest preview version
m365 spfx project upgrade --preview --output text
Get instructions to upgrade the current SharePoint Framework project to the specified preview version
m365 spfx project upgrade --toVersion 1.12.1-rc.0 --output text
Get instructions to upgrade the current SharePoint Framework project to the latest SharePoint Framework version supported by the CLI for Microsoft 365 using pnpm
m365 spfx project upgrade --packageManager pnpm --output text
Get instructions to upgrade the current SharePoint Framework project to the latest SharePoint Framework version supported by the CLI for Microsoft 365
m365 spfx project upgrade --output text
Get instructions to upgrade the current SharePoint Framework project to the latest SharePoint Framework version supported by the CLI for Microsoft 365 using PowerShell
m365 spfx project upgrade --shell powershell --output text
Get instructions to upgrade the current SharePoint Framework project to the latest version of SharePoint Framework and save the findings in a CodeTour (https://aka.ms/codetour) file
m365 spfx project upgrade --output tour
RESPONSE
When upgrading an SPFx project built using version 1.15.0 to SPFx version 1.15.2, you'll get output similar to following (output is truncated):
JSON
[
{
"description": "Upgrade SharePoint Framework dependency package @microsoft/sp-core-library",
"id": "FN001001",
"file": "./package.json",
"position": {
"line": 15,
"character": 5
},
"resolution": "npm i -SE @microsoft/sp-core-library@1.15.2",
"resolutionType": "cmd",
"severity": "Required",
"title": "@microsoft/sp-core-library"
},
{
"description": "Update version in .yo-rc.json",
"id": "FN010001",
"file": "./.yo-rc.json",
"position": {
"line": 5,
"character": 5
},
"resolution": "{\\\n \"@microsoft/generator-sharepoint\": {\\\n \"version\": \"1.15.2\"\\\n }\\\n}",
"resolutionType": "json",
"severity": "Recommended",
"title": ".yo-rc.json version"
}
]
Text
Execute in bash
-----------------------
npm i -SE @microsoft/sp-core-library@1.15.2
./.yo-rc.json
-------------
Update version in .yo-rc.json:
{
"@microsoft/generator-sharepoint": {
"version": "1.15.2"
}
}
Markdown
# Upgrade project HelloWorld to v1.15.2
Date: 20/11/2022
## Findings
Following is the list of steps required to upgrade your project to SharePoint Framework version 1.15.2. Summary of the modifications is included at the end of the report.
### FN001001 @microsoft/sp-core-library | Required
Upgrade SharePoint Framework dependency package @microsoft/sp-core-library
Execute the following command:
`sh
npm i -SE @microsoft/sp-core-library@1.15.2
File: ./package.json:17:5
## Summary
### Execute script
`sh
npm i -SE @microsoft/sp-core-library@1.15.2
`
### Modify files
#### ./.yo-rc.json
Update version in .yo-rc.json:
`json
{
"@microsoft/generator-sharepoint": {
"version": "1.15.2"
}
}
`