Logic implemented

This commit is contained in:
Aliaxei Terentiev 2016-11-11 17:11:56 -08:00
parent 3738bd7bfd
commit 8896b08ecb
61 changed files with 1684 additions and 206 deletions

View File

@ -1,30 +0,0 @@
/**
* Represents SharePoint View object
*/
export interface ISPView {
Title: string;
Id: string;
ListId: string;
}
/**
* Represents SharePoint List object
*/
export interface ISPList {
Title: string;
Id: string;
}
/**
* Represents SharePoint REST service response for /_api/web/lists service call
*/
export interface ISPLists {
value: ISPList[];
}
/**
* Represents SharePoint REST service response for /_api/web/lists('id')/views service call
*/
export interface ISPViews {
value: ISPView[];
}

View File

@ -1,15 +0,0 @@
import * as SP from '../typings/SP';
/**
* Data Helpers interface
*/
export interface IDataHelper {
/**
* API to get lists from the source
*/
getLists(): Promise<ISPList[]>;
/**
* API to get views from the source
*/
getViews(listId: string): Promise<ISPView[]>;
}

View File

@ -1,38 +0,0 @@
import { ISPList, ISPView } from '../common/SPEntities';
import { IDataHelper } from './DataHelperBase';
/**
* MOCK data helper. Gets data from hardcoded values
*/
export class DataHelperMock implements IDataHelper {
/**
* hardcoded collection of lists
*/
private static _lists: ISPList[] = [{ Title: 'Test 1', Id: '1' }, { Title: 'Test 2', Id: '2' }, { Title: 'Test 3', Id: '3' }];
/**
* hardcoded collection of views
*/
private static _views: ISPView[] = [{ Title: 'All Items', Id: '1', ListId: '1' }, { Title: 'Demo', Id: '2', ListId: '1' }, { Title: 'All Items', Id: '1', ListId: '2' }, { Title: 'All Items', Id: '1', ListId: '3' }];
/**
* API to get lists from the source
*/
public getLists(): Promise<ISPList[]> {
return new Promise<ISPList[]>((resolve) => {
resolve(DataHelperMock._lists); // returning all the lists
});
}
/**
* API to get views from the source
*/
public getViews(listId: string): Promise<ISPView[]> {
return new Promise<ISPView[]>((resolve) => {
// filtering views based on list id
const result: ISPView[] = DataHelperMock._views.filter((value, index, array) => {
return value.ListId === listId;
});
resolve(result);
});
}
}

View File

@ -1,83 +0,0 @@
import {
IWebPartContext
} from '@microsoft/sp-webpart-base';
import { ISPList, ISPView, ISPLists, ISPViews } from '../common/SPEntities';
import { IDataHelper } from './DataHelperBase';
/**
* List with views interface
*/
interface ISPListWithViews extends ISPList {
/**
* List Views
*/
Views: ISPView[];
}
/**
* SharePoint Data Helper class.
* Gets information from current web
*/
export class DataHelperSP implements IDataHelper {
/**
* Web part context
*/
public context: IWebPartContext;
/**
* Loaded lists
*/
private _lists: ISPListWithViews[];
/**
* ctor
*/
public constructor(_context: IWebPartContext) {
this.context = _context;
}
/**
* API to get lists from the source
*/
public getLists(): Promise<ISPList[]> {
return this.context.httpClient.get(this.context.pageContext.web.absoluteUrl + `/_api/web/lists?$filter=Hidden eq false`) // sending the request to SharePoint REST API
.then((response: Response) => { // httpClient.get method returns a response object where json method creates a Promise of getting result
return response.json();
}).then((response: ISPLists) => { // response is an ISPLists object
return response.value;
});
}
/**
* API to get views from the source
*/
public getViews(listId: string): Promise<ISPView[]> {
if (listId && listId == '-1' || listId == '0')
return new Promise<ISPView[]>((resolve) => {
resolve(new Array<ISPView>());
});
//
// trying to get views from cache
//
const lists: ISPListWithViews[] = this._lists && this._lists.length && this._lists.filter((value, index, array) => { return value.Id === listId; });
if (lists && lists.length) {
return new Promise<ISPView[]>((resolve) => {
resolve(lists[0].Views);
});
}
else {
return this.context.httpClient.get(this.context.pageContext.web.absoluteUrl + '/_api/web/lists(\'' + listId + '\')/views') // requesting views from SharePoint REST API
.then((response: Response) => { // httpClient.get method returns a response object where json method creates a Promise of getting result
return response.json();
}).then((response: ISPViews) => { // response is an ISPViews object
var views = response.value;
if (!this._lists || !this._lists.length)
this._lists = new Array<ISPListWithViews>();
this._lists.push({ Id: listId, Title: '', Views: views });
return views;
});
}
}
}

View File

@ -1,29 +0,0 @@
declare namespace SP {
export class ClientContext {
static get_current(): ClientContext;
load(obj: any, ...rest: string[]): void;
executeQueryAsyncCallback(success: (result: any) => void, error: (error: any) => void);
}
namespace Taxonomy {
export class TaxonomySession {
static getTaxonomySession(spContext: ClientRect): TaxonomySession;
get_termStores(): ITermStoreCollection;
}
export interface ITermStore {
get_groups(): ITermGroupCollection;
}
export interface ITermStoreCollection {
get_item(index: number): ITermStore;
}
export interface ITermGroup {
}
export interface ITermGroupCollection {
get_item(index: number): ITermGroup;
}
}
}

View File

@ -18,4 +18,6 @@
"lib": true,
"temp": true
}
,
"typescript.tsdk": "./node_modules/typescript/lib"
}

View File

@ -15,7 +15,7 @@
"react": "node_modules/react/dist/react.min.js",
"react-dom": "node_modules/react-dom/dist/react-dom.min.js",
"react-dom/server": "node_modules/react-dom/dist/react-dom-server.min.js",
"knockout": "node_modules/knockout/build/output/knockout-latest.js"
"knockout": "node_modules/knockout/build/output/knockout-latest.debug.js"
},
"localizedResources": {
"termSetRequesterStrings": "webparts/termSetRequester/loc/{locale}.js"

View File

@ -12,6 +12,7 @@
"devDependencies": {
"@microsoft/sp-build-web": "~0.7.0",
"@microsoft/sp-module-interfaces": "~0.4.0",
"@microsoft/sp-webpart-base": "^0.1.0",
"@microsoft/sp-webpart-workbench": "~0.5.0",
"gulp": "~3.9.1",
"knockout": "^3.4.1"

View File

@ -9,6 +9,8 @@ import styles from './TermSetRequester.module.scss';
import * as strings from 'termSetRequesterStrings';
import { ITermSetRequesterWebPartProps } from './ITermSetRequesterWebPartProps';
import { TaxonomyControl } from './controls/TaxonomyControl';
export default class TermSetRequesterWebPart extends BaseClientSideWebPart<ITermSetRequesterWebPartProps> {
public constructor(context: IWebPartContext) {
@ -19,18 +21,13 @@ export default class TermSetRequesterWebPart extends BaseClientSideWebPart<ITerm
this.domElement.innerHTML = `
<div class="${styles.termSetRequester}">
<div class="${styles.container}">
<div class="ms-Grid-row ms-bgColor-themeDark ms-fontColor-white ${styles.row}">
<div class="ms-Grid-col ms-u-lg10 ms-u-xl8 ms-u-xlPush2 ms-u-lgPush1">
<span class="ms-font-xl ms-fontColor-white">Welcome to SharePoint!</span>
<p class="ms-font-l ms-fontColor-white">Customize SharePoint experiences using Web Parts.</p>
<p class="ms-font-l ms-fontColor-white">${this.properties.description}</p>
<a href="https://github.com/SharePoint/sp-dev-docs/wiki" class="ms-Button ${styles.button}">
<span class="ms-Button-label">Learn more</span>
</a>
</div>
</div>
</div>
</div>`;
const container: HTMLDivElement = this.domElement.querySelector('.' + styles.container) as HTMLDivElement;
var termStoreCtrl = new TaxonomyControl(this.context);
termStoreCtrl.render(container);
}
protected get propertyPaneSettings(): IPropertyPaneSettings {

View File

@ -0,0 +1,99 @@
/**
* Base interface for Taxonomy objects
*/
export interface ITermBase {
/**
* Unique identifier
*/
id: string;
/**
* Name
*/
name: string;
}
/**
* Term Store interface
*/
export interface ITermStore extends ITermBase {
}
/**
* Term Group interface
*/
export interface ITermGroup extends ITermBase {
/**
* Term Group's description
*/
description: string;
/**
* Term Store ID.
* It is added to be able to store hierarchy structure (and it helps to decrease amount of Ajax requests to SharePoint)
*/
termStoreId: string;
}
/**
* Term Set Interface
*/
export interface ITermSet extends ITermBase {
/**
* Description
*/
description?: string;
/**
* Term Group ID
* It is added to be able to store hierarchy structure (and it helps to decrease amount of Ajax requests to SharePoint)
*/
termGroupId?: string;
/**
* Term Store ID.
* It is added to be able to store hierarchy structure (and it helps to decrease amount of Ajax requests to SharePoint)
*/
termStoreId?: string;
}
/**
* Term interface`
*/
export interface ITerm extends ITermBase {
/**
* Description
*/
description: string;
/**
* Flag if the current term is a root term in a term set
*/
isRoot: boolean;
/**
* Term labels
*/
labels: ILabel[];
/**
* Number of child terms
*/
termsCount: number;
/**
* Term Set ID
* It is added to be able to store hierarchy structure (and it helps to decrease amount of Ajax requests to SharePoint)
*/
termSetId: string;
}
/**
* Term Label interface
*/
export interface ILabel {
/**
* Flag if the label is default for current language
*/
isDefaultForLanguage: boolean;
/**
* Label's value
*/
value: string;
/**
* Current Language
*/
language: string;
}

View File

@ -0,0 +1,47 @@
import * as ko from 'knockout';
import {
IWebPartContext
} from '@microsoft/sp-webpart-base';
import { TaxonomyControlView } from './TaxonomyControlView';
import { TaxonomyControlViewModel } from './TaxonomyControlViewModel';
/**
* Class that represents a control to render Taxonomy hierarchy
*/
export class TaxonomyControl {
/**
* View
*/
private view: TaxonomyControlView;
/**
* ViewModel
*/
private viewModel: TaxonomyControlViewModel;
/**
* ctor
* @param context: web part context
*/
constructor(context: IWebPartContext) {
this.view = new TaxonomyControlView();
this.viewModel = new TaxonomyControlViewModel(context);
}
/**
* Renders the control
*/
public render(element: HTMLElement): Promise<void> {
return new Promise<void>((resolve) => {
// renders html first
this.view.render(element).then(() => {
// inits view model
this.viewModel.init().then(() => {
// applies bindings
ko.applyBindings(this.viewModel, element);
resolve();
});
});
});
}
}

View File

@ -0,0 +1,66 @@
import {
ITermStore,
ITermSet,
ITermGroup,
ITerm
} from '../common/SPEntities';
import {
IWebPartContext
} from '@microsoft/sp-webpart-base';
import { IDataHelper } from '../data-helpers/DataHelperBase';
import { DataHelpersFactory } from '../data-helpers/DataHelpersFactory';
/**
* Taxonomy Control Model
*/
export class TaxonomyControlModel {
/**
* data helper
*/
private _dataHelper: IDataHelper;
/**
* ctor
* @param context: web part context
*/
constructor(context: IWebPartContext) {
this._dataHelper = DataHelpersFactory.createDataHelper(context);
}
/**
* API to get Term Stores
*/
public getTermStores(): Promise<ITermStore[]> {
return this._dataHelper.getTermStores();
}
/**
* API to get Term Groups by Term Store
*/
public getTermGroups(termStore: ITermStore): Promise<ITermGroup[]> {
return this._dataHelper.getTermGroups(termStore.id);
}
/**
* API to get Term Sets by Term Group
*/
public getTermSets(termGroup: ITermGroup): Promise<ITermSet[]> {
return this._dataHelper.getTermSets(termGroup);
}
/**
* API to get Terms by Term Set
*/
public getTerms(termSet: ITermSet): Promise<ITerm[]> {
return this._dataHelper.getTerms(termSet);
}
/**
* API to get Terms by Term
*/
public getChildTerms(term: ITerm): Promise<ITerm[]> {
return this._dataHelper.getChildTerms(term);
}
}

View File

@ -0,0 +1,60 @@
export class TaxonomyControlView {
private _template: string = `
<div>
<ul>
<!-- ko template: { name: 'termStoreTpl', foreach: termStores } -->
<!-- /ko -->
</ul>
</div>
<script id="termStoreTpl" type="text/html">
<li><b>Type: Term Store</b> Name: <span data-bind="text: name"></span>; ID: <span data-bind="text: id"></span>&nbsp;<a href="javascript:;" data-bind="text: (isExpanded() ? 'Collapse' : 'Expand'), click: actionClick"></a>
<ul data-bind="visible: isExpanded">
<!-- ko template: { name: 'termGroupTpl', foreach: termGroups } -->
<!-- /ko -->
</ul>
</li>
</script>
<script id="termGroupTpl" type="text/html">
<li><b>Type: Term Group</b> Name: <span data-bind="text: name"></span>; Description: <span data-bind="text: description"></span>&nbsp;<a href="javascript:;" data-bind="text: (isExpanded() ? 'Collapse' : 'Expand'), click: actionClick"></a>
<ul data-bind="visible: isExpanded">
<!-- ko template: { name: 'termSetTpl', foreach: termSets } -->
<!-- /ko -->
</ul>
</li>
</script>
<script id="termSetTpl" type="text/html">
<li><b>Type: Term Set</b> Name: <span data-bind="text: name"></span>; Description: <span data-bind="text: description"></span>&nbsp;<a href="javascript:;" data-bind="text: (isExpanded() ? 'Collapse' : 'Expand'), click: actionClick"></a>
<ul data-bind="visible: isExpanded">
<!-- ko template: { name: 'termTpl', foreach: terms } -->
<!-- /ko -->
</ul>
</li>
</script>
<script id="termTpl" type="text/html">
<li><b>Type: Term</b> Name: <span data-bind="text: name"></span>; ID: <span data-bind="text: id"></span>; Description: <span data-bind="text: description"></span>&nbsp;<a href="javascript:;" data-bind="visible: hasChildTerms, text: (isExpanded() ? 'Collapse' : 'Expand'), click: actionClick"></a>
Labels:<br/>
<div data-bind="foreach: labels">
<div>Value: <span data-bind="text: value"></span>; Language: <span data-bind="text: language"></span>; Is Default: <span data-bind="text: isDefaultForLanguage"></span></div>
</div>
<ul data-bind="visible: isExpanded">
<!-- ko template: { name: 'termTpl', foreach: terms } -->
<!-- /ko -->
</ul>
</li>
</script>
`;
/**
* Renders markup
*/
public render(element: HTMLElement): Promise<void> {
return new Promise<void>((resolve) => {
element.innerHTML = this._template;
resolve();
});
}
}

View File

@ -0,0 +1,313 @@
import * as ko from 'knockout';
import { TaxonomyControlModel } from './TaxonomyControlModel';
import {
IWebPartContext
} from '@microsoft/sp-webpart-base';
import {
ITermBase,
ITermStore,
ITermSet,
ITermGroup,
ITerm,
ILabel
} from '../common/SPEntities';
/**
* Taxonomy Control ViewModel class
*/
export class TaxonomyControlViewModel {
/**
* Collection of term store view models
*/
protected termStores: KnockoutObservableArray<TermStoreViewModel>;
/**
* Model
*/
private model: TaxonomyControlModel;
/**
* ctor
* @param context: web part context
*/
constructor(context: IWebPartContext) {
this.model = new TaxonomyControlModel(context);
this.termStores = ko.observableArray<TermStoreViewModel>();
}
/**
* Inits the view model object
*/
public init(): Promise<void> {
return new Promise<void>((resolve) => {
// loading top level items of the hierarchy
this.model.getTermStores().then((termStores) => {
const termStoreViewModels: TermStoreViewModel[] = [];
termStores.forEach((value) => {
termStoreViewModels.push(new TermStoreViewModel(this.model, value));
});
this.termStores(termStoreViewModels);
resolve();
});
});
}
}
/**
* Base viewmodel for all Taxonomy objects
*/
export class TermBaseViewModel {
/**
* Object's id
*/
protected id: string;
/**
* Name
*/
protected name: string;
/**
* Flag if the the item is expanded
*/
protected isExpanded: KnockoutObservable<boolean>;
/**
* Model
*/
protected model: TaxonomyControlModel;
/**
* ctor
* @param model: taxonomy control model
* @param entity: entity that is underline current view model
*/
constructor(model: TaxonomyControlModel, entity: ITermBase) {
this.model = model;
this.isExpanded = ko.observable<boolean>(false);
this.id = entity.id;
this.name = entity.name;
}
}
/**
* Term store viewmodel
*/
export class TermStoreViewModel extends TermBaseViewModel {
/**
* Term store entity
*/
private entity: ITermStore;
/**
* collection of viewmodels for term store groups
*/
protected termGroups: KnockoutObservableArray<TermGroupViewModel>;
/**
* ctor
* @param model: taxonomy control model
* @param entity: entity that is underline current view model
*/
constructor(model: TaxonomyControlModel, entity: ITermStore) {
super(model, entity);
this.entity = entity;
this.termGroups = ko.observableArray<TermGroupViewModel>();
}
/**
* Expand\collapse click handler
*/
protected actionClick(ev: MouseEvent): void {
this.isExpanded(!this.isExpanded());
const isExpanded = this.isExpanded();
if (isExpanded) {
const unwrappedGroups = ko.utils.unwrapObservable(this.termGroups);
if (!unwrappedGroups || !unwrappedGroups.length) {
this.model.getTermGroups(this.entity).then((termGroups) => {
const termGroupViewModels: TermGroupViewModel[] = [];
termGroups.forEach((value) => {
termGroupViewModels.push(new TermGroupViewModel(this.model, value));
});
this.termGroups(termGroupViewModels);
});
}
}
}
}
/**
* Term Group ViewModel
*/
export class TermGroupViewModel extends TermBaseViewModel {
/**
* Term Group entity
*/
private entity: ITermGroup;
/**
* Description
*/
protected description: string;
/**
* collection of viewmodels for nested term sets
*/
protected termSets: KnockoutObservableArray<TermSetViewModel>;
/**
* ctor
* @param model: taxonomy control model
* @param entity: entity that is underline current view model
*/
constructor(model: TaxonomyControlModel, entity: ITermGroup) {
super(model, entity);
this.entity = entity;
this.description = entity.description;
this.termSets = ko.observableArray<TermSetViewModel>();
}
/**
* Expand\collapse click handler
*/
protected actionClick(ev: MouseEvent): void {
this.isExpanded(!this.isExpanded());
const isExpanded = this.isExpanded();
if (isExpanded) {
const unwrappedSets = ko.utils.unwrapObservable(this.termSets);
if (!unwrappedSets || !unwrappedSets.length) {
this.model.getTermSets(this.entity).then((termSets) => {
const termSetViewModels: TermSetViewModel[] = [];
termSets.forEach((value) => {
termSetViewModels.push(new TermSetViewModel(this.model, value));
});
this.termSets(termSetViewModels);
});
}
}
}
}
/**
* Term Set View Model
*/
export class TermSetViewModel extends TermBaseViewModel {
/**
* Term Set entity
*/
private entity: ITermSet;
/**
* Description
*/
protected description: string;
/**
* collection of viewmodels for nested terms
*/
protected terms: KnockoutObservableArray<TermViewModel>;
/**
* ctor
* @param model: taxonomy control model
* @param entity: entity that is underline current view model
*/
constructor(model: TaxonomyControlModel, entity: ITermSet) {
super(model, entity);
this.entity = entity;
this.description = entity.description;
this.terms = ko.observableArray<TermViewModel>();
}
/**
* Expand\collapse click handler
*/
protected actionClick(ev: MouseEvent): void {
this.isExpanded(!this.isExpanded());
const isExpanded = this.isExpanded();
if (isExpanded) {
const unwrappedTerms = ko.utils.unwrapObservable(this.terms);
if (!unwrappedTerms || !unwrappedTerms.length) {
this.model.getTerms(this.entity).then((terms) => {
const termViewModels: TermViewModel[] = [];
terms.forEach((value) => {
termViewModels.push(new TermViewModel(this.model, value));
});
this.terms(termViewModels);
});
}
}
}
}
/**
* Term ViewModel
*/
export class TermViewModel extends TermBaseViewModel {
/**
* Term emtity
*/
private entity: ITerm;
/**
* Description
*/
protected description: string;
/**
* collection of viewmodels for nested terms
*/
protected terms: KnockoutObservableArray<TermViewModel>;
/**
* Flag if current term has child terms
*/
protected hasChildTerms: boolean;
/**
* Term's labels
*/
protected labels: ILabel[];
/**
* ctor
* @param model: taxonomy control model
* @param entity: entity that is underline current view model
*/
constructor(model: TaxonomyControlModel, entity: ITerm) {
super(model, entity);
this.entity = entity;
this.description = entity.description;
this.terms = ko.observableArray<TermViewModel>();
this.hasChildTerms = entity.termsCount > 0;
this.labels = entity.labels;
}
/**
* Expand\collapse click handler
*/
protected actionClick(ev: MouseEvent): void {
this.isExpanded(!this.isExpanded());
const isExpanded = this.isExpanded();
if (isExpanded) {
const unwrappedTerms = ko.utils.unwrapObservable(this.terms);
if (!unwrappedTerms || !unwrappedTerms.length) {
this.model.getChildTerms(this.entity).then((terms) => {
const termViewModels: TermViewModel[] = [];
terms.forEach((value) => {
termViewModels.push(new TermViewModel(this.model, value));
});
this.terms(termViewModels);
});
}
}
}
}

View File

@ -0,0 +1,32 @@
import {
ITermStore,
ITermSet,
ITermGroup,
ITerm
} from '../common/SPEntities';
/**
* Data Helpers interface
*/
export interface IDataHelper {
/**
* API to get Term Stores
*/
getTermStores(): Promise<ITermStore[]>;
/**
* API to get Term Groups by Term Store
*/
getTermGroups(termStoreId: string): Promise<ITermGroup[]>;
/**
* API to get Term Sets by Term Group
*/
getTermSets(termGroup: ITermGroup): Promise<ITermSet[]>;
/**
* API to get Terms by Term Set
*/
getTerms(termSet: ITermSet): Promise<ITerm[]>;
/**
* API to get Terms by Term
*/
getChildTerms(term: ITerm): Promise<ITerm[]>;
}

View File

@ -0,0 +1,185 @@
import {
ITermStore,
ITermSet,
ITermGroup,
ITerm
} from '../common/SPEntities';
import {
IDataHelper
} from './DataHelperBase';
/**
* Interface for Term store with groups
*/
interface ITermStoreWithGroups extends ITermStore {
/**
* nested groups
*/
groups?: ITermGroupWithTermSets[];
}
/**
* Interface for term group with term sets
*/
interface ITermGroupWithTermSets extends ITermGroup {
/**
* nested term sets
*/
termSets?: ITermSetWithTerms[];
}
/**
* Interface for term set with terms
*/
interface ITermSetWithTerms extends ITermSet {
/**
* nested terms
*/
terms?: ITermWithTerms[];
}
/**
* Interface for term with nested terms
*/
interface ITermWithTerms extends ITerm {
/**
* nested terms
*/
terms?: ITermWithTerms[];
}
/**
* MOCK data helper. Gets data from hardcoded values
*/
export class DataHelperMock implements IDataHelper {
private static _termStores: ITermStoreWithGroups[] = [{
name: 'Term Store 1',
id: 'E920D42D-1540-4E39-B3F6-3795FBEF7F21',
groups: [{
id: '6789F532-CCDE-44C4-AE45-2EC5FC509274',
termStoreId: 'E920D42D-1540-4E39-B3F6-3795FBEF7F21',
name: 'Group 1 from Term Store 1',
description: 'This is the first group of the first term store',
termSets: [{
name: 'TSet 1 Gr 1 TStore 1',
id: 'B12D3D77-7DEA-435E-B1AF-3175DC9851DF',
termGroupId: '6789F532-CCDE-44C4-AE45-2EC5FC509274',
termStoreId: 'E920D42D-1540-4E39-B3F6-3795FBEF7F21',
description: 'Term Set 1 from Group 1 from Term Store 1',
terms: [{
id: '1494A0ED-0866-4082-92A8-1C83D5B117C4',
termSetId: 'B12D3D77-7DEA-435E-B1AF-3175DC9851DF',
name: 'T 1 TSet 1 Gr 1 TStore 1',
description: 'Term 1 from Term Set 1 from Group 1 from Term Store 1',
labels: [{
isDefaultForLanguage: true,
value: 'Term Label',
language: 'en-US'
}],
terms: [{
id: '1494A0ED-0866-4082-92A8-1C83D5B117C4',
termSetId: 'B12D3D77-7DEA-435E-B1AF-3175DC9851DF',
name: 'T 1.1 TSet 1 Gr 1 TStore 1',
description: 'Term 1 from Term Set 1 from Group 1 from Term Store 1',
labels: [{
isDefaultForLanguage: true,
value: 'Term Label',
language: 'en-US'
}],
termsCount: 0,
isRoot: false
}],
termsCount: 1,
isRoot: true
}]
}, {
id: '6783B7F9-41CA-4405-A85C-5C74B98AC81C',
termGroupId: '6789F532-CCDE-44C4-AE45-2EC5FC509274',
termStoreId: 'E920D42D-1540-4E39-B3F6-3795FBEF7F21',
name: 'TSet 2 Gr 1 TStore 1',
description: 'Term Set 2 from Group 1 from Term Store 1',
terms: []
}]
}, {
id: '9FC4934A-EFA2-4460-A5DB-1611B8B478FE',
termStoreId: 'E920D42D-1540-4E39-B3F6-3795FBEF7F21',
name: 'Group 2 from Term Store 1',
description: 'This is the second group of the first term store',
termSets: [{
id: '6AC24DB3-CF84-47D0-83E6-C118DD7C1D44',
termGroupId: '9FC4934A-EFA2-4460-A5DB-1611B8B478FE',
termStoreId: 'E920D42D-1540-4E39-B3F6-3795FBEF7F21',
name: 'TSet 1 Gr 2 TStore 1',
description: 'Term Set 1 from Group 2 from Term Store 1',
terms: []
}]
}]
}, {
name: 'Term Store 2',
id: 'BBB5D5CF-F39E-45D4-A71A-F74681133D03',
groups: [{
id: '96BD2791-BD83-4E1F-930C-0F2EBE943DFA',
termStoreId: 'BBB5D5CF-F39E-45D4-A71A-F74681133D03',
name: 'Group 1 from Term Store 2',
description: 'This is the first group of the second term store',
termSets: [{
id: 'DDF892AB-00D2-4F13-B70C-378BE3A95A1D',
termGroupId: '96BD2791-BD83-4E1F-930C-0F2EBE943DFA',
termStoreId: 'BBB5D5CF-F39E-45D4-A71A-F74681133D03',
name: 'TSet 1 Gr 1 TStore 2',
description: 'Term Set 1 from Group 1 from Term Store 2',
terms: []
}]
}]
}];
/**
* API to get Term Stores
*/
public getTermStores(): Promise<ITermStore[]> {
return new Promise<ITermStore[]>((resolve) => {
resolve(DataHelperMock._termStores);
});
}
/**
* API to get Term Groups by Term Store
*/
public getTermGroups(termStoreId: string): Promise<ITermGroup[]> {
return new Promise<ITermGroup[]>((resolve) => {
for (let i = 0, len = DataHelperMock._termStores.length; i < len; i++) {
const termStore = DataHelperMock._termStores[i];
if (termStore.id === termStoreId) {
resolve(termStore.groups);
return;
}
}
});
}
/**
* API to get Term Sets by Term Group
*/
public getTermSets(termGroup: ITermGroup): Promise<ITermSet[]> {
return new Promise<ITermSet[]>((resolve) => {
const termGroupWithTermSets: ITermGroupWithTermSets = termGroup as ITermGroupWithTermSets;
resolve(termGroupWithTermSets.termSets);
});
}
/**
* API to get Terms by Term Set
*/
public getTerms(termSet: ITermSet): Promise<ITerm[]> {
return new Promise<ITerm[]>((resolve) => {
const termSetWithTerms: ITermSetWithTerms = termSet as ITermSetWithTerms;
resolve(termSetWithTerms.terms);
});
}
/**
* API to get Terms by Term
*/
public getChildTerms(term: ITerm): Promise<ITerm[]> {
return new Promise<ITerm[]>((resolve) => {
const termWithTerms: ITermWithTerms = term as ITermWithTerms;
resolve(termWithTerms.terms);
});
}
}

View File

@ -0,0 +1,663 @@
/// <reference path="../../../../typings/SP/SP.d.ts" />
import {
IWebPartContext
} from '@microsoft/sp-webpart-base';
import {
ITermStore,
ITermSet,
ITermGroup,
ITerm
} from '../common/SPEntities';
import {
IDataHelper
} from './DataHelperBase';
/**
* Interface for terms with path property and nested terns
*/
interface ITermWithTerms extends ITerm {
/**
* Term's path
*/
path: string[];
/**
* child terms
*/
terms?: ITerms;
}
/**
* Interface that represents a map wit key term ID and value ITermWithTerms object
*/
interface ITerms {
[name: string]: ITermWithTerms;
}
/**
* Interface that represents a map with key term set ID and value ITerms object
*/
interface ITermSetTerms {
[name: string]: ITerms;
}
/**
* SharePoint Data Helper class.
* Gets information from current web
*/
export class DataHelperSP implements IDataHelper {
/**
* cached term stores. This property can be changed to static to be able to use the same cache in different web parts
*/
private _loadedTermStores: SP.Taxonomy.ITermStoreCollection;
/**
* cached terms' hierarchy. This property can be changed to static to be able to use the same cache in different web parts
*/
private _loadedTermsHierarchy: ITermSetTerms = {};
/**
* cached terms' flat list. This property can be changed to static to be able to use the same cache in different web parts
*/
private _loadedTermsFlat: ITerms[] = [];
/**
* Web part context
*/
public context: IWebPartContext;
/**
* ctor
* @param context: web part context
*/
public constructor(_context: IWebPartContext) {
this.context = _context;
}
/**
* API to get Term Stores
*/
public getTermStores(): Promise<ITermStore[]> {
return new Promise<ITermStore[]>((resolve) => {
// term stores have been already loaded
if (this._loadedTermStores) {
// converting SP.Taxonomy.ITermStore object to ITermStore objects
const termStoreEntities: ITermStore[] = this.getTermStoreEntities(this._loadedTermStores);
resolve(termStoreEntities);
return;
}
//
// need to load term stores
//
this.loadScripts().then(() => { // loading scripts first
const taxonomySession = this.taxonomySession;
let termStores = taxonomySession.get_termStores();
this.clientContext.load(termStores);
this.clientContext.executeQueryAsync(() => {
// converting SP.Taxonomy.ITermStore object to ITermStore objects
const termStoreEntities: ITermStore[] = this.getTermStoreEntities(termStores);
// caching loaded term stores
this._loadedTermStores = termStores;
resolve(termStoreEntities);
}, () => {
resolve([]);
});
});
});
}
/**
* API to get Term Groups by Term Store
*/
public getTermGroups(termStoreId: string): Promise<ITermGroup[]> {
return new Promise<ITermGroup[]>((resolve) => {
this.getTermStoreById(termStoreId).then((termStore) => { // getting the term store
if (!termStore) {
resolve([]);
return;
}
let groups = termStore.get_groups();
//
// if Groups property is not loaded get_count will throw an error that will be handled to retrieve groups
//
try {
if (!groups.get_count()) { // this will throw error if groups were not loaded
resolve([]);
return;
}
// converting SP.Taxonomy.ITermGroup object to ITermGroup objects
resolve(this.getTermGroupEntities(groups, termStore.get_id().toString()));
}
catch (ex) { // retrieving groups
this.clientContext.load(groups);
this.clientContext.executeQueryAsync(() => {
// converting SP.Taxonomy.ITermGroup object to ITermGroup objects
resolve(this.getTermGroupEntities(groups, termStore.get_id().toString()));
}, () => {
resolve([]);
});
}
finally {
}
});
});
}
/**
* API to get Term Sets by Term Group
*/
public getTermSets(termGroup: ITermGroup): Promise<ITermSet[]> {
return new Promise<ITermSet[]>((resolve) => {
this.getTermStoreById(termGroup.termStoreId).then((termStore) => { // getting term store by id
if (!termStore) {
resolve([]);
return;
}
this.getTermGroupById(termStore, termGroup.id).then((group) => { // getting term group by id
if (!group) {
resolve([]);
return;
}
let termSets = group.get_termSets();
//
// if termSets property is not loaded get_count will throw an error that will be handled to retrieve term sets
//
try {
if (!termSets.get_count()) { // this will throw error if term sets were not loaded
resolve([]);
return;
}
//converting SP.Taxonomy.ITermSet object to ITermSet object
resolve(this.getTermSetEntities(termSets, termGroup.id, termGroup.termStoreId));
}
catch (ex) { // retrieving term sets
this.clientContext.load(termSets);
this.clientContext.executeQueryAsync(() => {
//converting SP.Taxonomy.ITermSet object to ITermSet object
resolve(this.getTermSetEntities(termSets, termGroup.id, termGroup.termStoreId));
}, () => {
resolve([]);
});
}
finally {
}
});
});
});
}
/**
* API to get Terms by Term Set
*/
public getTerms(termSet: ITermSet): Promise<ITerm[]> {
return new Promise<ITerm[]>((resolve) => {
// checking if terms were previously loaded
if (this._loadedTermsHierarchy[termSet.id]) {
const termSetTerms = this._loadedTermsHierarchy[termSet.id];
// converting ITerms object to collection of ITerm objects
resolve(this.getTermEntities(termSetTerms));
return;
}
//
// need to load terms
//
this.getTermStoreById(termSet.termStoreId).then((termStore) => { // getting store by id
if (!termStore) {
resolve([]);
return;
}
this.getTermGroupById(termStore, termSet.termGroupId).then((group) => { // getting group by id
if (!group) {
resolve([]);
return;
}
this.getTermSetById(termStore, group, termSet.id).then((set) => { // getting term set by id
if (!set) {
resolve([]);
return;
}
let allTerms: SP.Taxonomy.ITermCollection;
//
// if terms property is not loaded get_count will throw an error that will be handled to retrieve terms
//
try {
allTerms = set.getAllTerms();
if (!allTerms.get_count()) { // this will throw error if terms were not loaded
resolve([]);
return;
}
// caching terms
this._loadedTermsHierarchy[termSet.id] = this.buildTermsHierarchy(allTerms, termSet.id);
// converting ITerms object to collection of ITerm objects
resolve(this.getTermEntities(this._loadedTermsHierarchy[termSet.id]));
}
catch (ex) { // retrieving terms
this.clientContext.load(allTerms, 'Include(Id, Name, Description, IsRoot, TermsCount, PathOfTerm, Labels)');
this.clientContext.executeQueryAsync(() => {
// caching terms
this._loadedTermsHierarchy[termSet.id] = this.buildTermsHierarchy(allTerms, termSet.id);
// converting ITerms object to collection of ITerm objects
resolve(this.getTermEntities(this._loadedTermsHierarchy[termSet.id]));
}, () => {
resolve([]);
});
}
finally { }
});
});
});
});
}
/**
* API to get Terms by Term
*/
public getChildTerms(term: ITerm): Promise<ITerm[]> {
return new Promise<ITerm[]>((resolve) => {
if (!this._loadedTermsFlat.length) {
//
// We can add logic to retrieve term from term Store
// But I'll skip it for this example
//
resolve([]);
return;
}
let terms: ITerms;
// iterating through flat list of terms to find needed one
for (let i = 0, len = this._loadedTermsFlat.length; i < len; i++) {
const currTerm = this._loadedTermsFlat[i][term.id];
if (currTerm) {
terms = currTerm.terms;
break;
}
}
if (!terms) {
resolve([]);
return;
}
// converting ITerms object to collection of ITerm objects
resolve(this.getTermEntities(terms));
});
}
/**
* Loads scripts that are needed to work with taxonomy
*/
private loadScripts(): Promise<void> {
return new Promise<void>((resolve) => {
//
// constructing path to Layouts folder
//
let layoutsUrl: string = this.context.pageContext.site.absoluteUrl;
if (layoutsUrl.lastIndexOf('/') === layoutsUrl.length - 1)
layoutsUrl = layoutsUrl.slice(0, -1);
layoutsUrl += '/_layouts/15/';
this.loadScript(layoutsUrl + 'init.js', 'Sod').then(() => { // loading init.js
return this.loadScript(layoutsUrl + 'sp.runtime.js', 'sp_runtime_initialize'); // loading sp.runtime.js
}).then(() => {
return this.loadScript(layoutsUrl + 'sp.js', 'sp_initialize'); // loading sp.js
}).then(() => {
return this.loadScript(layoutsUrl + 'sp.taxonomy.js', 'SP.Taxonomy'); // loading sp.taxonomy.js
}).then(() => {
resolve();
});
});
}
/**
* Loads script
* @param url: script src
* @param globalObjectName: name of global object to check if it is loaded to the page
*/
private loadScript(url: string, globalObjectName: string): Promise<void> {
return new Promise<void>((resolve) => {
let isLoaded = true;
if (globalObjectName.indexOf('.') !== -1) {
const props = globalObjectName.split('.');
let currObj: any = window;
for (let i = 0, len = props.length; i < len; i++) {
if (!currObj[props[i]]) {
isLoaded = false;
break;
}
currObj = currObj[props[i]];
}
}
else {
isLoaded = !!window[globalObjectName];
}
// checking if the script was previously added to the page
if (isLoaded || document.head.querySelector('script[src="' + url + '"]')) {
resolve();
return;
}
// loading the script
const script = document.createElement('script');
script.type = 'text/javascript';
script.src = url;
script.onload = () => {
resolve();
};
document.head.appendChild(script);
});
}
/**
* Taxonomy session getter
*/
private get taxonomySession(): SP.Taxonomy.TaxonomySession {
return SP.Taxonomy.TaxonomySession.getTaxonomySession(this.clientContext);
}
/**
* Client Context getter
*/
private get clientContext(): SP.ClientContext {
return SP.ClientContext.get_current();
}
/**
* Converts SP.Taxonomy.ITermStore objects to ITermStore objects
* @param termStores: SP.Taxonomy.ITermStoreCollection object
*/
private getTermStoreEntities(termStores: SP.Taxonomy.ITermStoreCollection): ITermStore[] {
if (!termStores)
return [];
const termStoreEntities: ITermStore[] = [];
for (let i = 0, len = termStores.get_count(); i < len; i++) {
const termStore = termStores.get_item(i);
termStoreEntities.push({
id: termStore.get_id().toString(),
name: termStore.get_name()
});
}
return termStoreEntities;
}
/**
* Converts SP.Taxonomy.ITermGroup objects to ITermGroup objects
* @param termGroups: SP.Taxonomy.ITermGroupCollection object
* @param termStoreId: the identifier of parent term store
*/
private getTermGroupEntities(termGroups: SP.Taxonomy.ITermGroupCollection, termStoreId: string): ITermGroup[] {
if (!termGroups)
return [];
const termGroupEntities: ITermGroup[] = [];
for (let i = 0, len = termGroups.get_count(); i < len; i++) {
const termGroup = termGroups.get_item(i);
termGroupEntities.push({
id: termGroup.get_id().toString(),
termStoreId: termStoreId,
name: termGroup.get_name(),
description: termGroup.get_description()
});
}
return termGroupEntities;
}
/**
* Converts SP.Taxonomy.ITermSet objects to ITermSet objects
* @param termSets: SP.Taxonomy.ITermSetCollection object
* @param termGroupId: the identifier of parent term group
* @param termStoreId: the identifier of parent term store
*/
private getTermSetEntities(termSets: SP.Taxonomy.ITermSetCollection, termGroupId: string, termStoreId: string): ITermSet[] {
if (!termSets)
return [];
const termSetEntities: ITermSet[] = [];
for (let i = 0, len = termSets.get_count(); i < len; i++) {
const termSet = termSets.get_item(i);
termSetEntities.push({
id: termSet.get_id().toString(),
name: termSet.get_name(),
description: termSet.get_description(),
termGroupId: termGroupId,
termStoreId: termStoreId
});
}
return termSetEntities;
}
/**
* Retrieves term store by its id
* @param termStoreId: the identifier of the store to retrieve
*/
private getTermStoreById(termStoreId: string): Promise<SP.Taxonomy.ITermStore> {
return new Promise<SP.Taxonomy.ITermStore>((resolve) => {
if (!this._loadedTermStores) { // term stores were not loaded, need to load them
this.getTermStores().then(() => {
return this.getTermStoreById(termStoreId);
});
}
else { // term stores are loaded
let termStore = null;
if (this._loadedTermStores) {
for (let i = 0, len = this._loadedTermStores.get_count(); i < len; i++) {
if (this._loadedTermStores.get_item(i).get_id().toString() === termStoreId) {
termStore = this._loadedTermStores.get_item(i);
break;
}
}
}
resolve(termStore);
}
});
}
/**
* Retrieves term group by its id and parent term store
* @param termStore: parent term store
* @param termGroupId: the identifier of the group to retrieve
*/
private getTermGroupById(termStore: SP.Taxonomy.ITermStore, termGroupId: string): Promise<SP.Taxonomy.ITermGroup> {
return new Promise<SP.Taxonomy.ITermGroup>((resolve) => {
if (!termStore || !termGroupId) {
resolve(null);
return;
}
let result: SP.Taxonomy.ITermGroup;
//
// if Groups property is not loaded get_count will throw an error that will be handled to retrieve groups
//
try {
const groups: SP.Taxonomy.ITermGroupCollection = termStore.get_groups();
const groupsCount: number = groups.get_count();
const groupIdUpper = termGroupId.toUpperCase();
for (let i = 0; i < groupsCount; i++) {
const currGroup: SP.Taxonomy.ITermGroup = groups.get_item(i);
if (currGroup.get_id().toString().toUpperCase() === groupIdUpper) {
result = currGroup;
break;
}
}
if (!result) { // throwing an exception to try to load the group from server again
throw new Error();
}
resolve(result);
}
catch (ex) { // retrieving the groups from server
result = termStore.getGroup(termGroupId);
this.clientContext.load(result);
this.clientContext.executeQueryAsync(() => {
resolve(result);
}, () => {
resolve(null);
});
}
finally { }
});
}
/**
* Retrieves term set by its id, parent group and parent store
* @param termStore: parent term store
* @param termGroup: parent term group
* @param termSetId: the identifier of the term set to retrieve
*/
private getTermSetById(termStore: SP.Taxonomy.ITermStore, termGroup: SP.Taxonomy.ITermGroup, termSetId: string): Promise<SP.Taxonomy.ITermSet> {
return new Promise<SP.Taxonomy.ITermSet>((resolve) => {
if (!termGroup || !termSetId) {
resolve(null);
return;
}
let result: SP.Taxonomy.ITermSet;
//
// if termSets property is not loaded get_count will throw an error that will be handled to retrieve term sets
//
try {
const termSets: SP.Taxonomy.ITermSetCollection = termGroup.get_termSets();
const setsCount: number = termSets.get_count();
const setIdUpper = termSetId.toUpperCase();
for (let i = 0; i < setsCount; i++) {
const currSet: SP.Taxonomy.ITermSet = termSets.get_item(i);
if (currSet.get_id().toString().toUpperCase() === setIdUpper) {
result = currSet;
break;
}
}
if (!result) { // throwing an exception to try to load the term set from server again
throw new Error();
}
resolve(result);
}
catch (ex) {
result = termStore.getTermSet(termSetId);
this.clientContext.load(result);
this.clientContext.executeQueryAsync(() => {
resolve(result);
}, () => {
resolve(null);
});
}
finally { }
});
}
/**
* Builds terms' hierarchy and also caches flat list of terms
* @param terms: SP.Taxonomy.ITermCollection object
* @param termSetId: the indetifier of parent term set
*/
private buildTermsHierarchy(terms: SP.Taxonomy.ITermCollection, termSetId: string): ITerms {
if (!terms)
return {};
const tree: ITerms = {};
const flat: ITerms = {};
//
// Iterating through terms to collect flat list and create ITermWithTerms instances
//
for (let i = 0, len = terms.get_count(); i < len; i++) {
const term = terms.get_item(i);
// creating instance
const termEntity: ITermWithTerms = {
id: term.get_id().toString(),
name: term.get_name(),
description: term.get_description(),
labels: [],
termsCount: term.get_termsCount(),
isRoot: term.get_isRoot(),
path: term.get_pathOfTerm().split(';'),
termSetId: termSetId
};
//
// settings labels
//
const labels = term.get_labels();
for (let lblIdx = 0, lblLen = labels.get_count(); lblIdx < lblLen; lblIdx++) {
const lbl = labels.get_item(lblIdx);
termEntity.labels.push({
isDefaultForLanguage: lbl.get_isDefaultForLanguage(),
value: lbl.get_value(),
language: lbl.get_language()
});
}
// if term is root we need to add it to the tree
if (termEntity.isRoot) {
tree[termEntity.id] = termEntity;
}
// adding term entity to flat list
flat[termEntity.id] = termEntity;
}
const keys = Object.keys(flat);
//
// iterating through flat list of terms to build the tree structure
//
for (let keyIdx = 0, keysLength = keys.length; keyIdx < keysLength; keyIdx++) {
const key = keys[keyIdx];
const currentTerm = flat[key];
// skipping root items
if (currentTerm.isRoot) continue;
// getting parent term name
const termParentName = currentTerm.path[currentTerm.path.length - 2];
//
// second iteration to get parent term in flat list
//
for (let keySecondIndex = 0; keySecondIndex < keysLength; keySecondIndex++) {
const secondTerm = flat[keys[keySecondIndex]];
if (secondTerm.name === termParentName) {
if (!secondTerm.terms)
secondTerm.terms = {};
secondTerm.terms[currentTerm.id] = currentTerm;
}
}
}
this._loadedTermsFlat.push(flat);
return tree;
}
/**
* Converts ITerms object to collection of ITerm objects
* @param terms: ITerms object
*/
private getTermEntities(terms: ITerms): ITerm[] {
const termsKeys = Object.keys(terms);
const termEntities: ITerm[] = [];
for (let keyIdx = 0, keysLength = termsKeys.length; keyIdx < keysLength; keyIdx++) {
termEntities.push(terms[termsKeys[keyIdx]]);
}
return termEntities;
}
}

View File

@ -0,0 +1,207 @@
/**
* SP namespace
*/
declare namespace SP {
/**
* Client Context class
*/
export class ClientContext {
/**
* API to get current context
*/
static get_current(): ClientContext;
/**
* API to load client objects
*/
load(obj: any, ...rest: string[]): void;
/**
* API to execute query
*/
executeQueryAsync(success?: (result: any) => void, error?: (error: any) => void);
}
/**
* Base collection interface
*/
export interface ICollectionBase {
/**
* API to get count of items in the collection
*/
get_count(): number;
}
/**
* Taxonomy namespace
*/
namespace Taxonomy {
/**
* Taxonomy Session class
*/
export class TaxonomySession {
/**
* API to get current Taxonomy Session
* @param spContext: current Client Context
*/
static getTaxonomySession(spContext: ClientContext): TaxonomySession;
/**
* API to get term stores
*/
get_termStores(): ITermStoreCollection;
}
/**
* Base interface of taxonomy objects
*/
export interface ITermBase {
/**
* API to get ID
*/
get_id(): any;
/**
* API to get name
*/
get_name(): string;
}
/**
* Term Store interface
*/
export interface ITermStore extends ITermBase {
/**
* API to get all groups in the term store
*/
get_groups(): ITermGroupCollection;
/**
* API to get group by its id
*/
getGroup(id: string): ITermGroup;
/**
* API to get term set by its id
*/
getTermSet(id: string): ITermSet;
}
/**
* Term Stores Collection interface
*/
export interface ITermStoreCollection extends ICollectionBase {
/**
* Gets item by index
*/
get_item(index: number): ITermStore;
}
/**
* Term Group interface
*/
export interface ITermGroup extends ITermBase {
/**
* API to get description
*/
get_description(): string;
/**
* API to get term sets from the group
*/
get_termSets(): ITermSetCollection;
}
/**
* Term Groups Collection inteface
*/
export interface ITermGroupCollection extends ICollectionBase {
/**
* Gets item by index
*/
get_item(index: number): ITermGroup;
}
/**
* Term Set Interface
*/
export interface ITermSet extends ITermBase {
/**
* API to get description
*/
get_description(): string;
/**
* API to get flat list of all terms in the Term set
*/
getAllTerms(): ITermCollection;
}
/**
* Term Sets collection interface
*/
export interface ITermSetCollection extends ICollectionBase {
/**
* Gets item by index
*/
get_item(index: number): ITermSet;
}
/**
* Term interface
*/
export interface ITerm extends ITermBase {
/**
* API to get description
*/
get_description(): string;
/**
* API to get labels
*/
get_labels(): ILabelCollection;
/**
* API to get flag if current term is root term
*/
get_isRoot(): boolean;
/**
* API to get child terms count
*/
get_termsCount(): number;
/**
* API to get path of the term in defauld lcid
*/
get_pathOfTerm(): string;
}
/**
* Terms Collection interface
*/
export interface ITermCollection extends ICollectionBase {
/**
* Gets item by index
*/
get_item(index: number): ITerm;
}
/**
* Labels collection interface
*/
export interface ILabelCollection extends ICollectionBase {
/**
* Gets item by index
*/
get_item(index: number): ILabel;
}
/**
* Label interface
*/
export interface ILabel {
/**
* API to get flag if current label is default for the language
*/
get_isDefaultForLanguage(): boolean;
/**
* API to get language
*/
get_language(): string;
/**
* API to get label's value
*/
get_value(): string;
}
}
}

View File

@ -16,3 +16,4 @@
/// <reference path="whatwg-fetch/whatwg-fetch.d.ts" />
/// <reference path="knockout/knockout.d.ts" />
/// <reference path="combokeys/combokeys.d.ts" />
/// <referehce path="SP/SP.d.ts />