diff --git a/docs/documentation/docs/controls/ModernTaxonomyPicker.md b/docs/documentation/docs/controls/ModernTaxonomyPicker.md index 1033f44e3..a9ef52a09 100644 --- a/docs/documentation/docs/controls/ModernTaxonomyPicker.md +++ b/docs/documentation/docs/controls/ModernTaxonomyPicker.md @@ -176,6 +176,7 @@ The ModernTaxonomyPicker control can be configured with the following properties | isLightDismiss | boolean | no | Whether the panel can be light dismissed. | | isBlocking | boolean | no | Whether the panel uses a modal overlay or not. | | onRenderActionButton | function | no | Optional custom renderer for adding e.g. a button with additional actions to the terms in the tree view. | +| isPathRendered | boolean | no | Whether the terms will be rendered with the term label or the full path up to the root. | ## Standalone TaxonomyTree control diff --git a/src/controls/modernTaxonomyPicker/ModernTaxonomyPicker.tsx b/src/controls/modernTaxonomyPicker/ModernTaxonomyPicker.tsx index f0b490c60..04bca5927 100644 --- a/src/controls/modernTaxonomyPicker/ModernTaxonomyPicker.tsx +++ b/src/controls/modernTaxonomyPicker/ModernTaxonomyPicker.tsx @@ -37,14 +37,16 @@ import { } from '@pnp/sp/taxonomy'; import { TermItemSuggestion } from './termItem/TermItemSuggestion'; import { ModernTermPicker } from './modernTermPicker/ModernTermPicker'; -import { IModernTermPickerProps, ITermItemProps } from './modernTermPicker/ModernTermPicker.types'; +import { IModernTermPickerProps, ITermItemProps, ITermItemStyles } from './modernTermPicker/ModernTermPicker.types'; import { TermItem } from './termItem/TermItem'; import { IReadonlyTheme } from '@microsoft/sp-component-base'; +import { ITermLabel } from '@pnp/sp/taxonomy/types'; export type Optional = Pick, K> & Omit; export interface IModernTaxonomyPickerProps { allowMultipleSelections?: boolean; + isPathRendered?: boolean; termSetId: string; anchorTermId?: string; panelTitle: string; @@ -126,12 +128,36 @@ export function ModernTaxonomyPicker(props: IModernTaxonomyPickerProps) { onClosePanel(); } + async function getParentTree(term: ITermInfo): Promise { + let currentParent = term.parent; + if(!currentParent) { + const fullTerm = await taxonomyService.getTermById(Guid.parse(props.termSetId), Guid.parse(term.id)); + currentParent = fullTerm.parent; + } + if(!currentParent) { // Top-level term reached, no parents. + return undefined; + } else { + currentParent.parent = await getParentTree(currentParent); + return currentParent; + } + } + + async function addParentInformationToTerms(filteredTerms: ITermInfo[]): Promise { + for(const filteredTerm of filteredTerms) { + const termParent = await getParentTree(filteredTerm); + filteredTerm.parent = termParent; + } + + return filteredTerms; + } + async function onResolveSuggestions(filter: string, selectedItems?: ITermInfo[]): Promise { if (filter === '') { return []; } const filteredTerms = await taxonomyService.searchTerm(Guid.parse(props.termSetId), filter, currentLanguageTag, props.anchorTermId ? Guid.parse(props.anchorTermId) : Guid.empty); - const filteredTermsWithoutSelectedItems = filteredTerms.filter((term) => { + const filteredTermsWithParentInformation = props.isPathRendered ? await addParentInformationToTerms(filteredTerms) : filteredTerms; + const filteredTermsWithoutSelectedItems = filteredTermsWithParentInformation.filter((term) => { if (!selectedItems || selectedItems.length === 0) { return true; } @@ -171,14 +197,29 @@ export function ModernTaxonomyPicker(props: IModernTaxonomyPickerProps) { ); } - function onRenderItem(itemProps: ITermItemProps): JSX.Element { - let labels = itemProps.item.labels.filter((name) => name.languageTag === currentLanguageTag && name.isDefault); + function getLabelsForCurrentLanguage(item: ITermInfo): ITermLabel[] { + let labels = item.labels.filter((name) => name.languageTag === currentLanguageTag && name.isDefault); if (labels.length === 0) { - labels = itemProps.item.labels.filter((name) => name.languageTag === currentTermStoreInfo.defaultLanguageTag && name.isDefault); + labels = item.labels.filter((name) => name.languageTag === currentTermStoreInfo.defaultLanguageTag && name.isDefault); } + return labels; + } + function onRenderItem(itemProps: ITermItemProps): JSX.Element { + const labels = getLabelsForCurrentLanguage(itemProps.item); + let fullParentPrefixes: string[] = [ labels[0].name ]; + + if(props.isPathRendered) { + let currentTermProps = itemProps.item; + while(currentTermProps.parent !== undefined) { + let currentParentLabels = getLabelsForCurrentLanguage(currentTermProps.parent); + fullParentPrefixes.push(currentParentLabels[0].name); + currentTermProps = currentTermProps.parent; + } + fullParentPrefixes = fullParentPrefixes.reverse(); + } return labels.length > 0 ? ( - {labels[0].name} + {fullParentPrefixes.join(":")} ) : null; }