Skip to content

Commit 645cec6

Browse files
committed
Merge branch 'TheThor59-dev' into dev
2 parents 3624856 + d2d910f commit 645cec6

File tree

4 files changed

+79
-34
lines changed

4 files changed

+79
-34
lines changed

src/common/Constants.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,4 +108,6 @@ export const InvariantCulture: ICultureInfo = {
108108
MonthGenitiveNames: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December', ''],
109109
eras: [1, 'A.D.', null, 0]
110110
}
111-
};
111+
};
112+
113+
export const EmptyGuid: string = "00000000-0000-0000-0000-000000000000";

src/controls/taxonomyPicker/TermPicker.tsx

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import * as strings from 'ControlStrings';
99
import { Icon } from 'office-ui-fabric-react/lib/Icon';
1010
import { ExtensionContext } from '@microsoft/sp-extension-base';
1111
import { ITermSet } from "../../services/ISPTermStorePickerService";
12+
import { EmptyGuid } from '../../Common';
1213

1314
export class TermBasePicker extends BasePicker<IPickerTerm, IBasePickerProps<IPickerTerm>>
1415
{
@@ -117,13 +118,7 @@ export default class TermPicker extends React.Component<ITermPickerProps, ITermP
117118
isTermSetSelectable
118119
} = this.props;
119120

120-
let terms: IPickerTerm[] = [];
121-
if (termPickerHostProps.anchorId) {
122-
terms = await this.termsService.searchTermsByTermId(filterText, termPickerHostProps.anchorId,);
123-
}
124-
else {
125-
terms = await this.termsService.searchTermsByName(filterText, termPickerHostProps.termsetNameOrID);
126-
}
121+
let terms: IPickerTerm[] = await this.termsService.searchTermsByName(filterText);
127122
// Check if the termset can be selected
128123
if (isTermSetSelectable && !termPickerHostProps.anchorId) {
129124
// Retrieve the current termset

src/services/ISPTermStorePickerService.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,3 +80,13 @@ export interface ITerm {
8080
[property: string]: any
8181
};
8282
}
83+
84+
export interface ISuggestTerm {
85+
Id: string;
86+
DefaultLabel: string;
87+
Description: string;
88+
IsKeyword: boolean;
89+
IsSynonym: boolean;
90+
Paths: Array<string>;
91+
Synonyms: string;
92+
}

src/services/SPTermStorePickerService.ts

Lines changed: 64 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,11 @@ import { Environment, EnvironmentType } from '@microsoft/sp-core-library';
1010
import { IWebPartContext } from '@microsoft/sp-webpart-base';
1111
import { ITaxonomyPickerProps } from '../controls/taxonomyPicker/ITaxonomyPicker';
1212
import { IPickerTerm } from '../controls/taxonomyPicker/ITermPicker';
13-
import { ITermStore, ITerms, ITerm, IGroup, ITermSet } from './ISPTermStorePickerService';
13+
import { ITermStore, ITerms, ITerm, IGroup, ITermSet, ISuggestTerm } from './ISPTermStorePickerService';
1414
import SPTermStoreMockHttpClient from './SPTermStorePickerMockService';
1515
import { findIndex } from '@microsoft/sp-lodash-subset';
1616
import { ExtensionContext } from '@microsoft/sp-extension-base';
17+
import { EmptyGuid } from '../common/Constants';
1718

1819

1920
/**
@@ -23,6 +24,7 @@ export default class SPTermStorePickerService {
2324
private taxonomySession: string;
2425
private formDigest: string;
2526
private clientServiceUrl: string;
27+
private suggestionServiceUrl: string;
2628

2729
/**
2830
* Service constructor
@@ -31,6 +33,7 @@ export default class SPTermStorePickerService {
3133
if (Environment.type !== EnvironmentType.Local) {
3234
{
3335
this.clientServiceUrl = this.context.pageContext.web.absoluteUrl + '/_vti_bin/client.svc/ProcessQuery';
36+
this.suggestionServiceUrl = this.context.pageContext.web.absoluteUrl + "/_vti_bin/TaxonomyInternalService.json/GetSuggestions";
3437
}
3538
}
3639
}
@@ -270,12 +273,12 @@ export default class SPTermStorePickerService {
270273
* Retrieve all terms that starts with the searchText
271274
* @param searchText
272275
*/
273-
public searchTermsByName(searchText: string, termSet: string): Promise<IPickerTerm[]> {
276+
public searchTermsByName(searchText: string): Promise<IPickerTerm[]> {
274277
if (Environment.type === EnvironmentType.Local) {
275278
// If the running environment is local, load the data from the mock
276279
return SPTermStoreMockHttpClient.searchTermsByName(searchText);
277280
} else {
278-
return this.searchTermsByTermSet(searchText, this.props.termsetNameOrID);
281+
return this.searchTermsByTermSet(searchText);
279282
}
280283
}
281284

@@ -375,55 +378,72 @@ export default class SPTermStorePickerService {
375378
* @param searchText
376379
* @param termsetId
377380
*/
378-
private searchTermsByTermSet(searchText: string, termSet: string): Promise<IPickerTerm[]> {
381+
private searchTermsByTermSet(searchText: string): Promise<IPickerTerm[]> {
379382
if (Environment.type === EnvironmentType.Local) {
380383
// If the running environment is local, load the data from the mock
381384
return SPTermStoreMockHttpClient.searchTermsByName(searchText);
382385
} else {
383386
return new Promise<IPickerTerm[]>(resolve => {
384387
this.getTermStores().then(termStore => {
385-
let TermSetId = termSet;
386-
if (!this.isGuid(termSet)) {
388+
let TermSetId = this.props.termsetNameOrID;
389+
if (!this.isGuid(TermSetId)) {
387390
// Get the ID of the provided term set name
388-
const crntTermSet = this.getTermSetId(termStore, termSet);
391+
const crntTermSet = this.getTermSetId(termStore, TermSetId);
389392
if (crntTermSet) {
390393
TermSetId = this.cleanGuid(crntTermSet.Id);
391394
} else {
392395
resolve(null);
393396
return;
394397
}
395398
}
399+
if (termStore === undefined || termStore.length === 0) {
400+
resolve(null);
401+
return;
402+
}
396403

397-
let data = `<Request xmlns="http://schemas.microsoft.com/sharepoint/clientquery/2009" SchemaVersion="15.0.0.0" LibraryVersion="16.0.0.0" ApplicationName="Javascript Library"><Actions><ObjectPath Id="456" ObjectPathId="455" /><ObjectIdentityQuery Id="457" ObjectPathId="455" /><ObjectPath Id="459" ObjectPathId="458" /><ObjectIdentityQuery Id="460" ObjectPathId="458" /><ObjectPath Id="462" ObjectPathId="461" /><ObjectIdentityQuery Id="463" ObjectPathId="461" /><ObjectPath Id="465" ObjectPathId="464" /><SetProperty Id="466" ObjectPathId="464" Name="TermLabel"><Parameter Type="String">${searchText}</Parameter></SetProperty><SetProperty Id="467" ObjectPathId="464" Name="DefaultLabelOnly"><Parameter Type="Boolean">true</Parameter></SetProperty><SetProperty Id="468" ObjectPathId="464" Name="StringMatchOption"><Parameter Type="Number">0</Parameter></SetProperty><SetProperty Id="469" ObjectPathId="464" Name="ResultCollectionSize"><Parameter Type="Number">10</Parameter></SetProperty><SetProperty Id="470" ObjectPathId="464" Name="TrimUnavailable"><Parameter Type="Boolean">true</Parameter></SetProperty><ObjectPath Id="472" ObjectPathId="471" /><Query Id="473" ObjectPathId="471"><Query SelectAllProperties="false"><Properties /></Query><ChildItemQuery SelectAllProperties="false"><Properties><Property Name="IsRoot" SelectAll="true" /><Property Name="Id" SelectAll="true" /><Property Name="Name" SelectAll="true" /><Property Name="PathOfTerm" SelectAll="true" /><Property Name="TermSet" SelectAll="true" /></Properties></ChildItemQuery></Query></Actions><ObjectPaths><StaticMethod Id="455" Name="GetTaxonomySession" TypeId="{981cbc68-9edc-4f8d-872f-71146fcbb84f}" /><Method Id="458" ParentId="455" Name="GetDefaultKeywordsTermStore" /><Method Id="461" ParentId="458" Name="GetTermSet"><Parameters><Parameter Type="Guid">${TermSetId}</Parameter></Parameters></Method><Constructor Id="464" TypeId="{61a1d689-2744-4ea3-a88b-c95bee9803aa}" /><Method Id="471" ParentId="461" Name="GetTerms"><Parameters><Parameter ObjectPathId="464" /></Parameters></Method></ObjectPaths></Request>`;
404+
let data = {
405+
start: searchText,
406+
lcid : this.context.pageContext.web.language, // TODO : get the user's navitation LCID. Here it's the default web language LCID
407+
sspList: this.cleanGuid(termStore[0].Id),
408+
termSetList: TermSetId,
409+
anchorId: this.props.anchorId ? this.props.anchorId : EmptyGuid,
410+
isSpanTermStores: false,
411+
isSpanTermSets: false,
412+
isIncludeUnavailable: this.props.hideTagsNotAvailableForTagging === true,
413+
isIncludeDeprecated: this.props.hideDeprecatedTags === true,
414+
isAddTerms: false,
415+
isIncludePathData: false,
416+
excludeKeyword: false,
417+
excludedTermset: EmptyGuid
418+
};
398419

399420
const reqHeaders = new Headers();
400421
reqHeaders.append("accept", "application/json");
401-
reqHeaders.append("content-type", "application/xml");
422+
reqHeaders.append("content-type", "application/json");
402423

403424
const httpPostOptions: ISPHttpClientOptions = {
404425
headers: reqHeaders,
405-
body: data
426+
body: JSON.stringify(data)
406427
};
407428

408429

409-
return this.context.spHttpClient.post(this.clientServiceUrl, SPHttpClient.configurations.v1, httpPostOptions).then((serviceResponse: SPHttpClientResponse) => {
430+
return this.context.spHttpClient.post(this.suggestionServiceUrl, SPHttpClient.configurations.v1, httpPostOptions).then((serviceResponse: SPHttpClientResponse) => {
410431
return serviceResponse.json().then((serviceJSONResponse: any) => {
411-
// Retrieve the term collection results
412-
const termStoreResult: ITerms[] = serviceJSONResponse.filter((r: { [x: string]: string; }) => r['_ObjectType_'] === 'SP.Taxonomy.TermCollection');
413-
if (termStoreResult.length > 0) {
414-
// Retrieve all terms
415-
416-
let terms = termStoreResult[0]._Child_Items_;
417-
418-
let returnTerms: IPickerTerm[] = [];
419-
terms.forEach(term => {
420-
if (term.Name.toLowerCase().indexOf(searchText.toLowerCase()) !== -1) {
421-
returnTerms.push(this.convertTermToPickerTerm(term));
422-
}
423-
});
424-
resolve(returnTerms);
432+
const groups = serviceJSONResponse.d.Groups;
433+
if (groups && groups.length > 0) {
434+
// Retrieve the term collection results
435+
const terms: ISuggestTerm[] = groups[0].Suggestions;
436+
if (terms.length > 0) {
437+
// Retrieve all terms
438+
439+
let returnTerms: IPickerTerm[] = terms.map((term: ISuggestTerm) => this.convertSuggestTermToPickerTerm(term));
440+
resolve(returnTerms);
441+
return;
442+
}
443+
425444
}
426-
return null;
445+
446+
resolve([]);
427447
});
428448
});
429449
});
@@ -552,4 +572,22 @@ export default class SPTermStorePickerService {
552572
termSetName: term.TermSet.Name
553573
};
554574
}
575+
576+
private convertSuggestTermToPickerTerm(term: ISuggestTerm): IPickerTerm {
577+
let path: string = "";
578+
let termSetName: string = "";
579+
if (term.Paths && term.Paths.length > 0) {
580+
const fullPath = term.Paths[0].replace(/^\[/, "").replace(/\]$/, "");
581+
const fullPathParts = fullPath.split(":");
582+
path = fullPathParts.join(";") + ";" + term.DefaultLabel;
583+
termSetName = fullPathParts[0];
584+
}
585+
return {
586+
key: this.cleanGuid(term.Id),
587+
name: term.DefaultLabel,
588+
path: path,
589+
termSet: EmptyGuid, // TermSet Guid is not given with suggestion
590+
termSetName: termSetName
591+
};
592+
}
555593
}

0 commit comments

Comments
 (0)