Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Full metadata term path display #1270

Merged
merged 4 commits into from
Aug 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/documentation/docs/controls/ModernTaxonomyPicker.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
53 changes: 47 additions & 6 deletions src/controls/modernTaxonomyPicker/ModernTaxonomyPicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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<T, K extends keyof T> = Pick<Partial<T>, K> & Omit<T, K>;

export interface IModernTaxonomyPickerProps {
allowMultipleSelections?: boolean;
isPathRendered?: boolean;
termSetId: string;
anchorTermId?: string;
panelTitle: string;
Expand Down Expand Up @@ -126,12 +128,36 @@ export function ModernTaxonomyPicker(props: IModernTaxonomyPickerProps) {
onClosePanel();
}

async function getParentTree(term: ITermInfo): Promise<ITermInfo> {
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<ITermInfo[]> {
for(const filteredTerm of filteredTerms) {
const termParent = await getParentTree(filteredTerm);
filteredTerm.parent = termParent;
}

return filteredTerms;
}

async function onResolveSuggestions(filter: string, selectedItems?: ITermInfo[]): Promise<ITermInfo[]> {
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;
}
Expand Down Expand Up @@ -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 ? (
<TermItem languageTag={currentLanguageTag} termStoreInfo={currentTermStoreInfo} {...itemProps}>{labels[0].name}</TermItem>
<TermItem languageTag={currentLanguageTag} termStoreInfo={currentTermStoreInfo} {...itemProps}>{fullParentPrefixes.join(":")}</TermItem>
) : null;
}

Expand Down