Skip to content

Commit f7d0d35

Browse files
committed
Merge branch 'siata13-dev' into dev
2 parents 430721e + af3e665 commit f7d0d35

File tree

17 files changed

+624
-43
lines changed

17 files changed

+624
-43
lines changed
21.9 KB
Loading

docs/documentation/docs/controls/TaxonomyPicker.md

Lines changed: 88 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -34,15 +34,13 @@ import { TaxonomyPicker, IPickerTerms } from "@pnp/spfx-controls-react/lib/Taxon
3434
- Use the `TaxonomyPicker` control in your code as follows:
3535

3636
```TypeScript
37-
<TaxonomyPicker
38-
allowMultipleSelections={true}
39-
termsetNameOrID="Countries"
40-
panelTitle="Select Term"
41-
label="Taxonomy Picker"
42-
context={this.props.context}
43-
onChange={this.onTaxPickerChange}
44-
isTermSetSelectable={false}
45-
/>
37+
<TaxonomyPicker allowMultipleSelections={true}
38+
termsetNameOrID="Countries"
39+
panelTitle="Select Term"
40+
label="Taxonomy Picker"
41+
context={this.props.context}
42+
onChange={this.onTaxPickerChange}
43+
isTermSetSelectable={false} />
4644
```
4745

4846
- With the `onChange` property you can capture the event of when the terms in the picker has changed:
@@ -53,6 +51,51 @@ private onTaxPickerChange(terms : IPickerTerms) {
5351
}
5452
```
5553

54+
## Term actions
55+
56+
Since version `1.12.0`, you can apply term actions to all terms or specific ones. Term actions could for instance be used to retrieve the labels of the term, or retrieve other information. These term actions can be implemented as follows:
57+
58+
```typescript
59+
<TaxonomyPicker allowMultipleSelections={true}
60+
termsetNameOrID="Countries"
61+
panelTitle="Select Term"
62+
label="Taxonomy Picker"
63+
context={this.props.context}
64+
onChange={this.onServicePickerChange}
65+
isTermSetSelectable={false}
66+
termActions={{
67+
actions: [{
68+
title: "Update term label",
69+
iconName: "LocaleLanguage",
70+
id: "UpdateTermLabel",
71+
actionCallback: async (taxService: SPTermStorePickerService, term: ITerm) => {
72+
return {
73+
updateActionType: UpdateType.updateTermLabel,
74+
value: `${term.Name} (updated)`
75+
};
76+
},
77+
applyToTerm: (term: ITerm) => (true) // Applying the action to all terms
78+
}]
79+
}} />
80+
```
81+
82+
![Term action sample](../assets/term-action.png)
83+
84+
We also provided a default term action which you can use to retrieve the term its labels and will update the term text in the TaxonomyPicker hierarchy.
85+
86+
```typescript
87+
<TaxonomyPicker allowMultipleSelections={true}
88+
termsetNameOrID="Countries"
89+
panelTitle="Select Term"
90+
label="Taxonomy Picker"
91+
context={this.props.context}
92+
onChange={this.onServicePickerChange}
93+
isTermSetSelectable={false}
94+
termActions={{
95+
actions: [new TermLabelAction("Get Labels")]
96+
}} />
97+
```
98+
5699
## Implementation
57100

58101
The TaxonomyPicker control can be configured with the following properties:
@@ -71,6 +114,7 @@ The TaxonomyPicker control can be configured with the following properties:
71114
| disabledTermIds | string[] | no | Specify which terms should be disabled in the term set so that they cannot be selected. |
72115
| disableChildrenOfDisabledParents | boolean | no | Specify if you want to disable the child terms when their parent is disabled. |
73116
| anchorId | string | no | Set the anchorid to a child term in the TermSet to be able to select terms from that level and below. |
117+
| termActions | ITermActions | no | Allows to execute custom action on the term like e.g. get other term labelsITermActions. |
74118

75119
Interface `IPickerTerm`
76120

@@ -86,4 +130,39 @@ Interface `IPickerTerms`
86130

87131
An Array of IPickerTerm
88132

133+
Interface `ITermActions`
134+
135+
| Property | Type | Required | Description | Default |
136+
| ---- | ---- | ---- | ---- | ---- |
137+
| actions | ITermAction[] | yes | The array of supported actions | |
138+
| termActionsDisplayStyle | TermActionsDisplayStyle | no | Defines how to display term action button, available options: text, icon, text and icon | text |
139+
| termActionsDisplayMode | TermActionsDisplayMode | no | Defines how to display term actions, as buttons or dropdown | buttons |
140+
| initialize | (spTermService: SPTermStorePickerService) => Promise\<void\> | no | Initializes the term action with the taxonomy service |
141+
142+
Interface `ITermAction`
143+
144+
| Property | Type | Required | Description |
145+
| ---- | ---- | ---- | ---- |
146+
| id | string | yes | Unique id of the term action |
147+
| title | string | yes | Action title |
148+
| iconName | string | no | Name of the icon to be used to display action |
149+
| applyToTerm | (currentTerm: ITerm) => Promise\<boolean\> \| boolean | yes | Method checks if the current term is supported |
150+
| actionCallback | (spTermService: SPTermStorePickerService, currentTerm: ITerm) => Promise\<UpdateAction\> | yes | Method to be executed when action is fired |
151+
| initialize | (spTermService: SPTermStorePickerService) => Promise\<void\> | no | Initializes the term action with the taxonomy service |
152+
153+
154+
Interface `UpdateAction`
155+
156+
| Property | Type | Required | Description |
157+
| ---- | ---- | ---- | ---- |
158+
| updateActionType | UpdateType | yes | Defines the type of update you want to perform |
159+
| value | string | no | New term label value to update. Only required when you want to update the term |
160+
161+
Enum `UpdateType`
162+
163+
| Value |
164+
| ---- |
165+
| updateTermLabel |
166+
| updateTermsTree |
167+
89168
![](https://telemetry.sharepointpnp.com/sp-dev-fx-controls-react/wiki/controls/Placeholder)

src/controls/taxonomyPicker/ITaxonomyPicker.ts

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import { ApplicationCustomizerContext } from '@microsoft/sp-application-base';
22
import { IPickerTerms } from './ITermPicker';
3-
import { ITermStore, IGroup, ITermSet, ITerm } from '../../services/ISPTermStorePickerService';
4-
import SPTermStorePickerService from '../../services/SPTermStorePickerService';
3+
import { ITermSet, ITerm } from '../../services/ISPTermStorePickerService';
54
import { IWebPartContext } from '@microsoft/sp-webpart-base';
5+
import { ITermActions } from './termActions/ITermsActions';
6+
import SPTermStorePickerService from '../../services/SPTermStorePickerService';
67

78
/**
89
* PropertyFieldTermPickerHost properties interface
@@ -52,6 +53,17 @@ export interface ITaxonomyPickerProps {
5253
* Whether the property pane field is enabled or not.
5354
*/
5455
disabled?: boolean;
56+
57+
/**
58+
* Include standard term actions.
59+
*/
60+
includeDefaultTermActions?: boolean;
61+
62+
/**
63+
* Specifies the available term actions and their basic properties.
64+
*/
65+
termActions?: ITermActions;
66+
5567
/**
5668
* The method is used to get the validation error message and determine whether the input value is valid or not.
5769
*
@@ -77,7 +89,6 @@ export interface ITaxonomyPickerProps {
7789
* PropertyFieldTermPickerHost state interface
7890
*/
7991
export interface ITaxonomyPickerState {
80-
8192
termSetAndTerms? : ITermSet;
8293
errorMessage?: string;
8394
openPanel?: boolean;
@@ -98,8 +109,11 @@ export interface ITermParentProps extends ITermChanges {
98109
multiSelection: boolean;
99110
anchorId? : string;
100111
isTermSetSelectable?: boolean;
112+
termActions?: ITermActions;
113+
spTermService: SPTermStorePickerService;
101114

102115
autoExpand: () => void;
116+
updateTaxonomyTree: () => void;
103117
termSetSelectedChange?: (termSet: ITermSet, isChecked: boolean) => void;
104118
}
105119

@@ -114,8 +128,13 @@ export interface ITermProps extends ITermChanges {
114128
term: ITerm;
115129
multiSelection: boolean;
116130
disabled: boolean;
131+
termActions?: ITermActions;
132+
spTermService: SPTermStorePickerService;
133+
134+
updateTaxonomyTree: () => void;
117135
}
118136

119137
export interface ITermState {
120138
selected?: boolean;
139+
termLabel: string;
121140
}

src/controls/taxonomyPicker/ITermPicker.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
import { ApplicationCustomizerContext } from '@microsoft/sp-application-base';
22
import { IWebPartContext } from '@microsoft/sp-webpart-base';
33

4-
5-
64
/**
75
* Selected terms
86
*/

src/controls/taxonomyPicker/TaxonomyPicker.module.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
.contextualMenu {
2+
display: inline-block
3+
}
4+
15
.listItem {
26
height: 36px;
37
line-height: 36px;

src/controls/taxonomyPicker/TaxonomyPicker.tsx

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,14 @@ import TermPicker from './TermPicker';
77
import { IPickerTerms, IPickerTerm } from './ITermPicker';
88
import { ITaxonomyPickerProps, ITaxonomyPickerState } from './ITaxonomyPicker';
99
import SPTermStorePickerService from './../../services/SPTermStorePickerService';
10-
import { ITermSet, IGroup, ITerm } from './../../services/ISPTermStorePickerService';
10+
import { ITermSet, ITerm } from './../../services/ISPTermStorePickerService';
11+
1112
import styles from './TaxonomyPicker.module.scss';
1213
import { sortBy, uniqBy, cloneDeep, isEqual } from '@microsoft/sp-lodash-subset';
1314
import TermParent from './TermParent';
1415
import FieldErrorMessage from './ErrorMessage';
15-
import * as telemetry from '../../common/telemetry';
1616

17+
import * as telemetry from '../../common/telemetry';
1718

1819
/**
1920
* Image URLs / Base64
@@ -81,19 +82,30 @@ export class TaxonomyPicker extends React.Component<ITaxonomyPickerProps, ITaxon
8182
*/
8283
private loadTermStores(): void {
8384
this.termsService = new SPTermStorePickerService(this.props, this.props.context);
85+
86+
if (this.props.termActions && this.props.termActions.initialize) {
87+
this.props.termActions.initialize(this.termsService);
88+
// this.props.termActions.actions.forEach(x => {
89+
// x.initialize(this.termsService);
90+
// });
91+
}
92+
8493
this.termsService.getAllTerms(this.props.termsetNameOrID).then((response: ITermSet) => {
8594
// Check if a response was retrieved
86-
if (response !== null) {
87-
this.setState({
88-
termSetAndTerms: response,
89-
loaded: true
90-
});
91-
} else {
92-
this.setState({
93-
termSetAndTerms: null,
94-
loaded: true
95-
});
96-
}
95+
let termSetAndTerms = response ? response : null;
96+
this.setState({
97+
termSetAndTerms,
98+
loaded: true
99+
});
100+
});
101+
}
102+
103+
/**
104+
* Force update of the taxonomy tree - required by term action in case the term has been added, deleted or moved.
105+
*/
106+
private updateTaxonomyTree(): void {
107+
this.setState({
108+
termSetAndTerms: this.state.termSetAndTerms
97109
});
98110
}
99111

@@ -304,7 +316,12 @@ export class TaxonomyPicker extends React.Component<ITaxonomyPickerProps, ITaxon
304316
disabledTermIds={this.props.disabledTermIds}
305317
disableChildrenOfDisabledParents={this.props.disableChildrenOfDisabledParents}
306318
changedCallback={this.termsChanged}
307-
multiSelection={this.props.allowMultipleSelections} />
319+
multiSelection={this.props.allowMultipleSelections}
320+
spTermService={this.termsService}
321+
322+
updateTaxonomyTree={this.updateTaxonomyTree}
323+
termActions={this.props.termActions}
324+
/>
308325
</div>
309326
)
310327
}

src/controls/taxonomyPicker/Term.tsx

Lines changed: 46 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,25 @@ import { Checkbox } from 'office-ui-fabric-react/lib/Checkbox';
33
import { ITermProps, ITermState } from './ITaxonomyPicker';
44

55
import styles from './TaxonomyPicker.module.scss';
6+
import TermActionsControl from './termActions/TermActionsControl';
7+
import { UpdateAction, UpdateType } from './termActions';
68

79

810
/**
911
* Term component
1012
* Renders a selectable term
1113
*/
1214
export default class Term extends React.Component<ITermProps, ITermState> {
15+
1316
constructor(props: ITermProps) {
1417
super(props);
1518

1619
// Check if current term is selected
1720
let active = this.props.activeNodes.filter(item => item.key === this.props.term.Id);
1821

1922
this.state = {
20-
selected: active.length > 0
23+
selected: active.length > 0,
24+
termLabel: this.props.term.Name
2125
};
2226

2327
this._handleChange = this._handleChange.bind(this);
@@ -43,7 +47,8 @@ export default class Term extends React.Component<ITermProps, ITermState> {
4347
if (!this.props.multiSelection) {
4448
let active = nextProps.activeNodes.filter(item => item.key === this.props.term.Id);
4549
this.state = {
46-
selected: active.length > 0
50+
selected: active.length > 0,
51+
termLabel: this.state.termLabel
4752
};
4853
}
4954
}
@@ -63,23 +68,55 @@ export default class Term extends React.Component<ITermProps, ITermState> {
6368
return styles.termEnabled;
6469
}
6570

71+
private termActionCallback = (updateAction: UpdateAction): void => {
72+
if (updateAction == null) {
73+
return;
74+
}
75+
76+
if (updateAction.updateActionType === UpdateType.updateTermLabel) {
77+
this.props.term.Name = updateAction.value;
78+
this.setState({
79+
termLabel: updateAction.value
80+
});
81+
}
82+
else {
83+
this.props.updateTaxonomyTree();
84+
}
85+
}
86+
6687
/**
6788
* Default React render
6889
*/
6990
public render(): JSX.Element {
7091
const styleProps: React.CSSProperties = {
7192
marginLeft: `${(this.props.term.PathDepth * 30)}px`
7293
};
94+
const checkBoxStyle: React.CSSProperties = {
95+
display: "inline-flex"
96+
};
7397

7498
return (
75-
<div className={`${styles.listItem} ${styles.term}`} style={styleProps}>
76-
<Checkbox
77-
checked={this.state.selected}
78-
disabled={this.props.term.IsDeprecated || !this.props.term.IsAvailableForTagging || this.props.disabled}
79-
className={this.getClassName()}
80-
label={this.props.term.Name}
81-
onChange={this._handleChange} />
99+
<div>
100+
<div className={`${styles.listItem} ${styles.term}`} style={styleProps}>
101+
<div>
102+
<Checkbox
103+
checked={this.state.selected}
104+
style={checkBoxStyle}
105+
disabled={this.props.term.IsDeprecated || !this.props.term.IsAvailableForTagging || this.props.disabled}
106+
className={this.getClassName()}
107+
label={this.state.termLabel}
108+
onChange={this._handleChange} />
109+
</div>
110+
{
111+
this.props.termActions &&
112+
<TermActionsControl term={this.props.term}
113+
termActions={this.props.termActions}
114+
termActionCallback={this.termActionCallback}
115+
spTermService={this.props.spTermService} />
116+
}
117+
</div>
82118
</div>
119+
83120
);
84121
}
85122
}

src/controls/taxonomyPicker/TermParent.tsx

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,16 @@ export default class TermParent extends React.Component<ITermParentProps, ITermP
106106
disabled = parentPath && parentPath.length > 0;
107107
}
108108

109-
return <Term key={term.Id} term={term} termset={this.props.termset.Id} activeNodes={this.props.activeNodes} changedCallback={this.props.changedCallback} multiSelection={this.props.multiSelection} disabled={disabled} />;
109+
return <Term key={term.Id}
110+
term={term}
111+
termset={this.props.termset.Id}
112+
activeNodes={this.props.activeNodes}
113+
changedCallback={this.props.changedCallback}
114+
multiSelection={this.props.multiSelection}
115+
disabled={disabled}
116+
termActions={this.props.termActions}
117+
updateTaxonomyTree={this.props.updateTaxonomyTree}
118+
spTermService={this.props.spTermService} />;
110119
})
111120
}
112121
</div>

0 commit comments

Comments
 (0)