azure-devops-ui
Version:
React components for building web UI in Azure DevOps
118 lines (117 loc) • 7.46 kB
JavaScript
import "../../CommonImports";
import "../../Core/core.css";
import "./IdentityPickerSuggestionsList.css";
import * as React from "react";
import { format } from '../../Core/Util/String';
import { Button } from '../../Button';
import { Icon } from '../../Icon';
import { Persona, PersonaSize } from '../../Persona';
import * as Resources from '../../Resources.IdentityPicker';
import { Tooltip } from '../../TooltipEx';
import { KeyCode } from '../../Util';
import { getScopedGroupParts, getSignInAddress, isGithubUser, isRemoveMRUFixEnabled, shouldShowIdentityCard } from "../IdentityPickerDropdown/IdentityPickerUtils";
import { IdentityType } from "../IdentityPickerDropdown/SharedIdentityPicker.Props";
export class IdentityPickerSuggestionItem extends React.Component {
constructor(props) {
super(props);
this.contactCardButtonRef = React.createRef();
this.removeButtonRef = React.createRef();
this.handleButtonKeyDown = (keyCode, targetRef) => (e) => {
if (isRemoveMRUFixEnabled() && e.which === keyCode && targetRef.current) {
targetRef.current.focus();
e.preventDefault();
e.stopPropagation();
// Track keyboard navigation between buttons
document.dispatchEvent(new CustomEvent('vss-telemetry-proxy', {
detail: {
area: "vss-identity-picker",
component: "IdentityPickerSuggestionItem",
feature: "IdentityPicker.MRU",
level: 3,
method: "handleButtonKeyDown",
message: "Navigate between MRU buttons with arrow keys"
},
bubbles: true
}));
}
};
this.onRemoveButtonKeyDown = this.handleButtonKeyDown(KeyCode.rightArrow, this.contactCardButtonRef);
this.onContactCardButtonKeyDown = this.handleButtonKeyDown(KeyCode.leftArrow, this.removeButtonRef);
this.state = {
focused: false
};
this.onFocus = this.onFocus.bind(this);
this.onBlur = this.onBlur.bind(this);
}
onFocus() {
this.setState({ focused: true });
}
onBlur() {
this.setState({ focused: false });
}
render() {
const identity = this.props.item;
const showRemoveButton = isRemoveMRUFixEnabled() && !!this.props.onRemoveFromMRU && identity.isMru;
let signInAddress = getSignInAddress(identity);
let displayName = identity.displayName;
const scopedGroupParts = getScopedGroupParts(identity);
if (scopedGroupParts) {
displayName = scopedGroupParts.name;
if (!signInAddress) {
signInAddress = scopedGroupParts.scope;
}
}
return (React.createElement("div", { className: "bolt-picker-suggesteditem flex-row flex-grow flex-center scroll-hidden", onFocus: this.onFocus, onBlur: this.onBlur },
this.props.renderSuggestion && identity.entityType === IdentityType.Custom ? (this.props.renderSuggestion(this.props)) : (React.createElement("div", { className: "bolt-picker-suggesteditem-text flex-row flex-grow flex-center text-ellipsis" },
React.createElement(Persona, { ariaHidden: true, className: "bolt-picker-persona text-ellipsis", identity: identity, size: PersonaSize.size24 }),
React.createElement("div", { className: "bolt-picker-persona-name flex-column flex-grow" },
displayName && (React.createElement(Tooltip, { text: identity.displayName, overflowOnly: identity.displayName === displayName },
React.createElement("div", { className: "fontSizeM text-ellipsis" }, displayName))),
!signInAddress ? (undefined) : (React.createElement("div", { className: "flex-row" },
isGithubUser(identity) && (React.createElement(Icon, { className: "bolt-identitypicker-github-icon flex-row flex-center justify-center", iconName: "GitHubLogo" })),
React.createElement("div", { className: "fontSize secondary-text text-ellipsis" }, signInAddress)))))),
showRemoveButton && (React.createElement(Button, { ariaLabel: format(Resources.RemoveFromRecent, displayName), className: "identity-picker-delete-icon", iconProps: { iconName: "Cancel", className: "flex-shrink" }, onClick: (e) => {
this.props.onRemoveFromMRU && this.props.onRemoveFromMRU(identity);
e.preventDefault();
e.stopPropagation();
// Track remove button click
document.dispatchEvent(new CustomEvent('vss-telemetry-proxy', {
detail: {
area: "vss-identity-picker",
component: "IdentityPickerSuggestionItem",
feature: "IdentityPicker.MRU",
level: 3,
method: "onRemoveButtonClick",
message: "Remove button clicked to remove identity from MRU"
},
bubbles: true
}));
}, onBlur: this.props.onBlur, onFocus: this.props.onFocus, onKeyDown: this.onRemoveButtonKeyDown, ref: this.removeButtonRef, subtle: true, tooltipProps: { text: format(Resources.RemoveFromRecent, displayName), showOnFocus: true }, tabIndex: this.state.focused ? 0 : -1, ariaHidden: this.state.focused ? false : true })),
!!this.props.onOpenPersonaCard && shouldShowIdentityCard(identity) && (React.createElement(Button, { ariaLabel: Resources.IdentityPickerProfileCardButtonTooltip, className: "bolt-contact-card-button flex-noshrink", iconProps: { iconName: "ContactCard", className: "flex-shrink" }, onClick: (e) => {
this.props.onOpenPersonaCard && this.props.onOpenPersonaCard(identity);
e.preventDefault();
}, onBlur: this.props.onBlur, onFocus: this.props.onFocus,
// TODO: When removing feature flag, change to: onKeyDown={this.onContactCardButtonKeyDown}
onKeyDown: showRemoveButton ? this.onContactCardButtonKeyDown : undefined, ref: this.contactCardButtonRef, subtle: true, tooltipProps: { text: Resources.IdentityPickerProfileCardButtonTooltip, showOnFocus: true }, tabIndex: this.state.focused ? 0 : -1, ariaHidden: this.state.focused ? false : true }))));
}
focus() {
if (isRemoveMRUFixEnabled() && this.removeButtonRef.current) {
this.removeButtonRef.current.focus();
// Track focus on remove button
document.dispatchEvent(new CustomEvent('vss-telemetry-proxy', {
detail: {
area: "vss-identity-picker",
component: "IdentityPickerSuggestionItem",
feature: "IdentityPicker.MRU",
level: 3,
method: "focus",
message: "Focus set on remove button"
},
bubbles: true
}));
}
else if (this.contactCardButtonRef.current) {
this.contactCardButtonRef.current.focus();
}
}
}