Added userValue to normalizedField

This commit is contained in:
Hugo Bernier 2021-01-06 03:34:46 -05:00
parent 91e7390041
commit 6d146dfe2f
8 changed files with 340 additions and 43 deletions

View File

@ -5,6 +5,44 @@
"id": "00406271-0276-406f-9666-512623eb6709",
"version": "1.1.0.0",
"isDomainIsolated": false,
"webApiPermissionRequests": [
{
"resource": "Microsoft Graph",
"scope": "User.Read"
},
{
"resource": "Microsoft Graph",
"scope": "People.Read"
},
{
"resource": "Microsoft Graph",
"scope": "Contacts.Read"
},
{
"resource": "Microsoft Graph",
"scope": "User.ReadBasic.All"
},
{
"resource": "Microsoft Graph",
"scope": "Calendars.Read"
},
{
"resource": "Microsoft Graph",
"scope": "Directory.Read.All"
},
{
"resource": "Microsoft Graph",
"scope": "User.Read.All"
},
{
"resource": "Microsoft Graph",
"scope": "Group.Read.All"
},
{
"resource": "Microsoft Graph",
"scope": "Files.Read.All"
}
],
"includeClientSideAssets": true,
"developer": {
"name": "PnP Community",

View File

@ -1,6 +1,6 @@
{
"name": "react-content-query-webpart",
"version": "1.0.16",
"version": "1.1.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@ -4910,6 +4910,183 @@
}
}
},
"@microsoft/mgt": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/@microsoft/mgt/-/mgt-2.0.1.tgz",
"integrity": "sha512-Qx1SU7J2CJ/8+pOjZWAl7qxoaAzXgf3ikSGeur5MoUTWOA7oENd8mZxuesur+dhJM6nMF9pG6ESrhnjuAr0ssA==",
"requires": {
"@microsoft/mgt-components": "2.0.1",
"@microsoft/mgt-element": "2.0.1",
"@microsoft/mgt-msal-provider": "2.0.1",
"@microsoft/mgt-proxy-provider": "2.0.1",
"@microsoft/mgt-sharepoint-provider": "2.0.1",
"@microsoft/mgt-teams-provider": "2.0.1"
}
},
"@microsoft/mgt-components": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/@microsoft/mgt-components/-/mgt-components-2.0.1.tgz",
"integrity": "sha512-36Jhd+BkIbYudjeRgXhlE7e2su+5O/RfbH4teAVbPDoc9KIX1Z+fLElgk09cG3FRSnRGr0GeOPYoVxSR7wBgqQ==",
"requires": {
"@microsoft/mgt-element": "2.0.1",
"@microsoft/microsoft-graph-client": "^2.2.1",
"@microsoft/microsoft-graph-types": "^1.27.0",
"@microsoft/microsoft-graph-types-beta": "github:microsoftgraph/msgraph-typescript-typings#beta",
"office-ui-fabric-core": "11.0.0"
},
"dependencies": {
"@microsoft/microsoft-graph-client": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/@microsoft/microsoft-graph-client/-/microsoft-graph-client-2.2.1.tgz",
"integrity": "sha512-fbDN3UJ+jtSP9llAejqmslMcv498YuIrS3OS/Luivb8OSjdUESZKdP0gcUunnuNIayePVT0/bGYSJTzAIptJQQ==",
"requires": {
"@babel/runtime": "^7.4.4",
"msal": "^1.4.4",
"tslib": "^1.9.3"
}
},
"msal": {
"version": "1.4.4",
"resolved": "https://registry.npmjs.org/msal/-/msal-1.4.4.tgz",
"integrity": "sha512-aOBD/L6jAsizDFzKxxvXxH0FEDjp6Inr3Ufi/Y2o7KCFKN+akoE2sLeszEb/0Y3VxHxK0F0ea7xQ/HHTomKivw==",
"requires": {
"tslib": "^1.9.3"
}
},
"office-ui-fabric-core": {
"version": "11.0.0",
"resolved": "https://registry.npmjs.org/office-ui-fabric-core/-/office-ui-fabric-core-11.0.0.tgz",
"integrity": "sha512-K6+KGnBXXjfSxxZpp+4oDXVLgUc//7OnXrn8F08VoJnGhEz27WUf4ZuMa32SjGoqirWlb4JlKkXbOpC9cis6dQ=="
}
}
},
"@microsoft/mgt-element": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/@microsoft/mgt-element/-/mgt-element-2.0.1.tgz",
"integrity": "sha512-GXf+y24ddpqb+CQY2qVn/gaVz/jCuplu8npbdAtKf7ZwTbp436bc3T+N2hzoOdLdv/T8feUOjbTtj7lIIQrB3Q==",
"requires": {
"@microsoft/microsoft-graph-client": "^2.2.1",
"idb": "^5.0.7",
"lit-element": "^2.4.0"
},
"dependencies": {
"@microsoft/microsoft-graph-client": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/@microsoft/microsoft-graph-client/-/microsoft-graph-client-2.2.1.tgz",
"integrity": "sha512-fbDN3UJ+jtSP9llAejqmslMcv498YuIrS3OS/Luivb8OSjdUESZKdP0gcUunnuNIayePVT0/bGYSJTzAIptJQQ==",
"requires": {
"@babel/runtime": "^7.4.4",
"msal": "^1.4.4",
"tslib": "^1.9.3"
}
},
"msal": {
"version": "1.4.4",
"resolved": "https://registry.npmjs.org/msal/-/msal-1.4.4.tgz",
"integrity": "sha512-aOBD/L6jAsizDFzKxxvXxH0FEDjp6Inr3Ufi/Y2o7KCFKN+akoE2sLeszEb/0Y3VxHxK0F0ea7xQ/HHTomKivw==",
"requires": {
"tslib": "^1.9.3"
}
}
}
},
"@microsoft/mgt-msal-provider": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/@microsoft/mgt-msal-provider/-/mgt-msal-provider-2.0.1.tgz",
"integrity": "sha512-fDGE1xFwno/U7d9aUAqBI8f3K5/dPVK1myxh58K9G8xql10WAC8wnbHgW6z6b1Fdifg/ImQXXj4UwLX+qOY/6g==",
"requires": {
"@microsoft/mgt-element": "2.0.1",
"@microsoft/microsoft-graph-client": "^2.2.1",
"msal": "^1.4.4"
},
"dependencies": {
"@microsoft/microsoft-graph-client": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/@microsoft/microsoft-graph-client/-/microsoft-graph-client-2.2.1.tgz",
"integrity": "sha512-fbDN3UJ+jtSP9llAejqmslMcv498YuIrS3OS/Luivb8OSjdUESZKdP0gcUunnuNIayePVT0/bGYSJTzAIptJQQ==",
"requires": {
"@babel/runtime": "^7.4.4",
"msal": "^1.4.4",
"tslib": "^1.9.3"
}
},
"msal": {
"version": "1.4.4",
"resolved": "https://registry.npmjs.org/msal/-/msal-1.4.4.tgz",
"integrity": "sha512-aOBD/L6jAsizDFzKxxvXxH0FEDjp6Inr3Ufi/Y2o7KCFKN+akoE2sLeszEb/0Y3VxHxK0F0ea7xQ/HHTomKivw==",
"requires": {
"tslib": "^1.9.3"
}
}
}
},
"@microsoft/mgt-proxy-provider": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/@microsoft/mgt-proxy-provider/-/mgt-proxy-provider-2.0.1.tgz",
"integrity": "sha512-qSkX0idPz658VhUQmFc8Gbn8ykeI/iue5arPTU+YQbQkV+qguK+bYdNZ8GYLUZ9EE5BrUqogEQT76eWfZCQjeA==",
"requires": {
"@microsoft/mgt-element": "2.0.1",
"@microsoft/microsoft-graph-client": "^2.2.1"
},
"dependencies": {
"@microsoft/microsoft-graph-client": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/@microsoft/microsoft-graph-client/-/microsoft-graph-client-2.2.1.tgz",
"integrity": "sha512-fbDN3UJ+jtSP9llAejqmslMcv498YuIrS3OS/Luivb8OSjdUESZKdP0gcUunnuNIayePVT0/bGYSJTzAIptJQQ==",
"requires": {
"@babel/runtime": "^7.4.4",
"msal": "^1.4.4",
"tslib": "^1.9.3"
}
},
"msal": {
"version": "1.4.4",
"resolved": "https://registry.npmjs.org/msal/-/msal-1.4.4.tgz",
"integrity": "sha512-aOBD/L6jAsizDFzKxxvXxH0FEDjp6Inr3Ufi/Y2o7KCFKN+akoE2sLeszEb/0Y3VxHxK0F0ea7xQ/HHTomKivw==",
"requires": {
"tslib": "^1.9.3"
}
}
}
},
"@microsoft/mgt-sharepoint-provider": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/@microsoft/mgt-sharepoint-provider/-/mgt-sharepoint-provider-2.0.1.tgz",
"integrity": "sha512-VaJyRLFGtGftFaI337sJ1ieLUgXeA0wms39hsDd8daE/vRSbZ9d6Ke5aIJmrseCgJprZZoJplbKXs9e1HwcWCg==",
"requires": {
"@microsoft/mgt-element": "2.0.1"
}
},
"@microsoft/mgt-teams-provider": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/@microsoft/mgt-teams-provider/-/mgt-teams-provider-2.0.1.tgz",
"integrity": "sha512-l+qe00KtZ5rqoGxlORMQHu9NyQ6yyi/qjfyuVU0mFhsR/9Caxo7MQEojWEnLxnmChX+W+O4gRbuphYc832xfcw==",
"requires": {
"@microsoft/mgt-element": "2.0.1",
"@microsoft/mgt-msal-provider": "2.0.1",
"@microsoft/microsoft-graph-client": "^2.2.1"
},
"dependencies": {
"@microsoft/microsoft-graph-client": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/@microsoft/microsoft-graph-client/-/microsoft-graph-client-2.2.1.tgz",
"integrity": "sha512-fbDN3UJ+jtSP9llAejqmslMcv498YuIrS3OS/Luivb8OSjdUESZKdP0gcUunnuNIayePVT0/bGYSJTzAIptJQQ==",
"requires": {
"@babel/runtime": "^7.4.4",
"msal": "^1.4.4",
"tslib": "^1.9.3"
}
},
"msal": {
"version": "1.4.4",
"resolved": "https://registry.npmjs.org/msal/-/msal-1.4.4.tgz",
"integrity": "sha512-aOBD/L6jAsizDFzKxxvXxH0FEDjp6Inr3Ufi/Y2o7KCFKN+akoE2sLeszEb/0Y3VxHxK0F0ea7xQ/HHTomKivw==",
"requires": {
"tslib": "^1.9.3"
}
}
}
},
"@microsoft/microsoft-graph-client": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@microsoft/microsoft-graph-client/-/microsoft-graph-client-1.1.0.tgz",
@ -4919,6 +5096,15 @@
"isomorphic-fetch": "^2.2.1"
}
},
"@microsoft/microsoft-graph-types": {
"version": "1.28.0",
"resolved": "https://registry.npmjs.org/@microsoft/microsoft-graph-types/-/microsoft-graph-types-1.28.0.tgz",
"integrity": "sha512-nb6nS+ISwa75t1lnO4J3zsNuJ7CHNrOgIVg1ptzAejkGuyJfkpJfx+0+UjyG+WXl9HL9KMeOxzaALBJflOah9Q=="
},
"@microsoft/microsoft-graph-types-beta": {
"version": "github:microsoftgraph/msgraph-typescript-typings#dec3e2507fdab4b6348ecabdd2e56189caaf05c2",
"from": "github:microsoftgraph/msgraph-typescript-typings#beta"
},
"@microsoft/node-core-library": {
"version": "3.13.0",
"resolved": "https://registry.npmjs.org/@microsoft/node-core-library/-/node-core-library-3.13.0.tgz",
@ -14002,6 +14188,16 @@
"to-regex-range": "^2.1.0"
}
},
"fsevents": {
"version": "1.2.13",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz",
"integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==",
"dev": true,
"optional": true,
"requires": {
"nan": "^2.12.1"
}
},
"glob-parent": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
@ -17567,26 +17763,6 @@
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
},
"fsevents": {
"version": "1.2.13",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz",
"integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==",
"dev": true,
"optional": true,
"requires": {
"bindings": "^1.5.0",
"nan": "^2.12.1"
},
"dependencies": {
"bindings": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
"integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
"dev": true,
"optional": true
}
}
},
"fstream": {
"version": "1.0.12",
"resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz",
@ -19189,6 +19365,11 @@
}
}
},
"idb": {
"version": "5.0.8",
"resolved": "https://registry.npmjs.org/idb/-/idb-5.0.8.tgz",
"integrity": "sha512-K9xInRkVbT3ZsYimD2KVj6B4E93IBvOjEQTryu99WuuN7G+7x3SzA79+yubbX0QRN9V64Gi+L+ulG5QYTVydOg=="
},
"ieee754": {
"version": "1.1.13",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz",
@ -21928,6 +22109,19 @@
"integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=",
"dev": true
},
"lit-element": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/lit-element/-/lit-element-2.4.0.tgz",
"integrity": "sha512-pBGLglxyhq/Prk2H91nA0KByq/hx/wssJBQFiYqXhGDvEnY31PRGYf1RglVzyLeRysu0IHm2K0P196uLLWmwFg==",
"requires": {
"lit-html": "^1.1.1"
}
},
"lit-html": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/lit-html/-/lit-html-1.3.0.tgz",
"integrity": "sha512-0Q1bwmaFH9O14vycPHw8C/IeHMk/uSDldVLIefu/kfbTBGIc44KGH6A8p1bDfxUfHdc8q6Ct7kQklWoHgr4t1Q=="
},
"livereload-js": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/livereload-js/-/livereload-js-2.4.0.tgz",
@ -27751,6 +27945,16 @@
}
}
},
"fsevents": {
"version": "1.2.13",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz",
"integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==",
"dev": true,
"optional": true,
"requires": {
"nan": "^2.12.1"
}
},
"is-accessor-descriptor": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",

View File

@ -12,6 +12,7 @@
"test": "gulp test"
},
"dependencies": {
"@microsoft/mgt": "^2.0.1",
"@microsoft/sp-core-library": "1.11.0",
"@microsoft/sp-lodash-subset": "1.11.0",
"@microsoft/sp-office-ui-fabric-core": "1.11.0",

View File

@ -0,0 +1,9 @@
import { IUserValue } from "./IUserValue";
export interface INormalizedResult {
textValue: string;
htmlValue: string;
rawValue: any;
jsonValue: any;
userValue?: IUserValue;
}

View File

@ -0,0 +1,4 @@
export interface IUserValue {
email: string;
name: string;
}

View File

@ -15,6 +15,7 @@ import { ListService, IListTitle } from './ListService';
import { SearchService } from './SearchService';
import { PeoplePickerService } from './PeoplePickerService';
import { TaxonomyService } from './TaxonomyService';
import { INormalizedResult } from '../dataContracts/INormalizedResult';
export class ContentQueryService implements IContentQueryService {
@ -75,7 +76,7 @@ export class ContentQueryService implements IContentQueryService {
return new Promise<IContentQueryTemplateContext>((resolve, reject) => {
// Initializes the base template context
let templateContext: IContentQueryTemplateContext = {
const templateContext: IContentQueryTemplateContext = {
pageContext: this.context.pageContext,
webUrl: querySettings.webUrl,
listId: querySettings.listId,
@ -85,13 +86,19 @@ export class ContentQueryService implements IContentQueryService {
callTimeStamp: callTimeStamp
};
// Builds the CAML query based on the webpart settings
let query = CamlQueryHelper.generateCamlQuery(querySettings);
// Builds the CAML query based on the web part settings
const query: string = CamlQueryHelper.generateCamlQuery(querySettings);
//TODO: Remove
console.log("Query", query);
//Log.info(this.logSource, Text.format("Generated CAML query {0}...", query), this.context.serviceScope);
// Queries the list with the generated caml query
// Queries the list with the generated CAML query
this.listService.getListItemsByQuery(querySettings.webUrl, querySettings.listId, query)
.then((data: any) => {
//TODO: Remove
console.log("List Service data", data);
// Updates the template context with the normalized query results
let normalizedResults = this.normalizeQueryResults(data.value, querySettings.viewFields);
templateContext.items = normalizedResults;
@ -257,7 +264,7 @@ export class ContentQueryService implements IContentQueryService {
return new Promise<IDropdownOption[]>((resolve, reject) => {
this.listService.getListTitlesFromWeb(webUrl).then((listTitles: IListTitle[]) => {
let options: IDropdownOption[] = [{ key: "", text: strings.ListTitleFieldPlaceholder }];
let listTitleOptions = listTitles.map((list) => { return { key: list.id, text: list.title }; });
const listTitleOptions = listTitles.map((list) => { return { key: list.id, text: list.title }; });
options = options.concat(listTitleOptions);
this.listTitleOptions = options;
resolve(options);
@ -290,9 +297,11 @@ export class ContentQueryService implements IContentQueryService {
// Otherwise gets the options asynchronously
return new Promise<IDropdownOption[]>((resolve, reject) => {
this.listService.getListFields(webUrl, listId, ['InternalName', 'Title', 'Sortable'], 'Title').then((data: any) => {
let sortableFields: any[] = data.value.filter((field) => { return field.Sortable == true; });
//TODO: Remove
console.log("Fields", data);
const sortableFields: any[] = data.value.filter((field) => { return field.Sortable == true; });
let options: IDropdownOption[] = [{ key: "", text: strings.queryFilterPanelStrings.queryFilterStrings.fieldSelectLabel }];
let orderByOptions: IDropdownOption[] = sortableFields.map((field) => { return { key: field.InternalName, text: Text.format("{0} \{\{{1}\}\}", field.Title, field.InternalName) }; });
const orderByOptions: IDropdownOption[] = sortableFields.map((field) => { return { key: field.InternalName, text: Text.format("{0} \{\{{1}\}\}", field.Title, field.InternalName) }; });
options = options.concat(orderByOptions);
this.orderByOptions = options;
resolve(options);
@ -576,31 +585,58 @@ export class ContentQueryService implements IContentQueryService {
* Normalizes the results coming from a CAML query into a userfriendly format for handlebars
* @param results : The results returned by a CAML query executed against a list
**************************************************************************************************/
private normalizeQueryResults(results: any[], viewFields: string[]): any[] {
private normalizeQueryResults(results: any[], viewFields: string[]): INormalizedResult[] {
//Log.verbose(this.logSource, "Normalizing results for the requested handlebars context...", this.context.serviceScope);
let normalizedResults: any[] = [];
// TODO: Remove
console.log("Results", results);
for (let result of results) {
const normalizedResults: INormalizedResult[] = results.map((result) => {
let normalizedResult: any = {};
let formattedCharsRegex = /_x00(20|3a|[c-f]{1}[0-9a-f]{1})_/gi;
for (let viewField of viewFields) {
//check if the intenal fieldname begins with a special character (_x00)
let viewFieldOdata = viewField;
let viewFieldOdata: string = viewField;
if (viewField.indexOf("_x00") == 0) {
viewFieldOdata = `OData_${viewField}`;
}
let formattedName = viewFieldOdata.replace(formattedCharsRegex, "_x005f_x00$1_x005f_");
formattedName = formattedName.replace(/_x00$/, "_x005f_x00");
const htmlValue: string = result.FieldValuesAsHtml[formattedName];
normalizedResult[viewField] = {
textValue: result.FieldValuesAsText[formattedName],
htmlValue: result.FieldValuesAsHtml[formattedName],
htmlValue: htmlValue,
rawValue: result[viewField] || result[viewField + 'Id'],
jsonValue: this.jsonParseField(result[viewField] || result[viewField + 'Id'])
};
// Try to extract the user email and name
const sipIndex = htmlValue.indexOf(`sip='`);
if (sipIndex > -1) {
// Get the email address
const sipValue = htmlValue.substring(sipIndex + 5, htmlValue.indexOf(`'`, sipIndex + 5));
const anchorEnd: number = htmlValue.lastIndexOf('</a>');
const anchorStart: number = htmlValue.substring(0, anchorEnd).lastIndexOf('>');
const name: string = htmlValue.substring(anchorStart + 1, anchorEnd);
normalizedResult[viewField].userValue = {
email: sipValue,
displayName: name
};
}
}
normalizedResults.push(normalizedResult);
}
return normalizedResult;
});
//TODO: Remove
console.log("Normalized results", normalizedResults);
return normalizedResults;
}

View File

@ -1,9 +1,9 @@
export enum QueryFilterFieldType {
Text = 1,
Number= 2,
Datetime = 3,
User = 4,
Lookup = 5,
Taxonomy = 6,
Url = 7
Text = 1,
Number = 2,
Datetime = 3,
User = 4,
Lookup = 5,
Taxonomy = 6,
Url = 7
}

View File

@ -31,6 +31,8 @@ import { IDynamicDataCallables }
import { IDynamicItem } from '../../common/dataContracts/IDynamicItem';
import { ThemeProvider, ThemeChangedEventArgs, IReadonlyTheme } from '@microsoft/sp-component-base';
import { Providers, SharePointProvider } from '@microsoft/mgt';
export default class ContentQueryWebPart
extends BaseClientSideWebPart<IContentQueryWebPartProps>
implements IDynamicDataCallables {
@ -95,6 +97,9 @@ export default class ContentQueryWebPart
// Register a handler to be notified if the theme variant changes
this._themeProvider.themeChangedEvent.add(this, this._handleThemeChangedEvent);
// ADDED: For MGT support
Providers.globalProvider = new SharePointProvider(this.context);
return new Promise<void>((resolve, reject) => {
this.ContentQueryService = new ContentQueryService(this.context, this.context.spHttpClient);
this.properties.webUrl = this.properties.siteUrl || this.properties.webUrl ? this.properties.webUrl : this.context.pageContext.web.absoluteUrl.toLocaleLowerCase().trim();