@boomerang-io/carbon-addons-boomerang-react
Version:
Carbon Addons for Boomerang apps
319 lines (316 loc) • 21 kB
JavaScript
import React, { useState, useEffect } from 'react';
import { useMutation } from 'react-query';
import { InlineLoading, HeaderMenu, HeaderMenuItem } from '@carbon/react';
import { CheckmarkFilled, AddAlt, GroupAccount, ChevronDown } from '@carbon/react/icons';
import sortBy from 'lodash.sortby';
import HeaderMenu$1 from './HeaderMenu.js';
import { resolver } from '../../config/servicesConfig.js';
import { prefix } from '../../internal/settings.js';
import { USER_PLATFORM_ROLE } from '../../constants/UserType.js';
/*
IBM Confidential
694970X, 69497O0
© Copyright IBM Corp. 2022, 2025
*/
const headerDropdownMenuContainerClassname = `${prefix}--header-dropdown-menu-container`;
const headerDropdownMenuLoadingClassname = `${prefix}--header-dropdown-menu-loading`;
const headerDropdownMenuSuccessClassname = `${prefix}--header-dropdown-menu-success`;
const headerDropdownMenuClassname = `${prefix}--header-dropdown-menu`;
const headerDropdownMenuListClassname = `${prefix}--bmrg-header-drop-down`;
const headerDropdownMenuItemContainerClassname = `${prefix}--header-dropdown-menu-item-container`;
const headerDropdownMenuItemClassname = `${prefix}--header-dropdown-menu-item`;
const headerDropdownMenuItemTextIconClassname = `${prefix}--header-dropdown-menu-item-text-icon`;
const headerDropdownMenuItemTextClassname = `${prefix}--header-dropdown-menu-item-text`;
const headerDropdownMenuItemIconClassname = `${prefix}--header-dropdown-menu-item-icon`;
const headerDropdownMenuItemAccountContainerClassname = `${prefix}--header-dropdown-menu-item-account-container`;
const headerDropdownMenuItemAccountClassname = `${prefix}--header-dropdown-menu-item-account`;
const headerDropdownMenuItemAccountIconsClassname = `${prefix}--header-dropdown-menu-item-account-icons`;
const headerDropdownMenuItemAccountGroupIconClassname = `${prefix}--header-dropdown-menu-item-account-group-icon`;
const headerDropdownMenuItemAccountChevronIconClassname = `${prefix}--header-dropdown-menu-item-account-chevron-icon`;
const headerDropdownMenuItemAccountSubmenuClassname = `${prefix}--header-dropdown-menu-item-account-submenu`;
const headerTeamSwitcherCreateTeamButtonContainerClassname = `${prefix}--header-team-switcher-create-team-button-container`;
const headerTeamSwitcherCreateTeamButtonClassname = `${prefix}--header-team-switcher-create-team-button`;
const headerTeamSwitcherCreateTeamButtonTextClassname = `${prefix}--header-team-switcher-create-team-button-text`;
const headerTeamSwitcherCreateTeamButtonIconClassname = `${prefix}--header-team-switcher-create-team-button-icon`;
function HeaderTeamSwitcher({ analyticsHelpers, baseServicesUrl, createJoinTeamTrigger, history, isLaunchpad, isLoadingTeamSwitcher, isSuccessTeamSwitcher, setIsSuccessTeamSwitcher, menuAriaLabelRecord, menuButtonId, menuListId, navigationPlatform, refetchUser, refetchNavigation, teamsQuery, trackEvent, user, userTeams, }) {
const [selectedTeam, setSelectedTeam] = useState();
const [openAccountSubmenuId, setOpenAccountSubmenuId] = useState("");
const hasUserTeams = Boolean(userTeams);
const showSelectTeamPurpose = navigationPlatform?.requireTeamPurpose;
const createTeamButtonText = showSelectTeamPurpose ? "Create Team" : "Create or Join Team";
const userTeamInstanceSwitcherDefault = user?.teamInstanceSwitcherDefault;
const teamLink = ({ teamId }) => {
return `${navigationPlatform.baseEnvUrl}/launchpad/teams/${teamId}`;
};
const { mutateAsync: mutateUserProfile, isLoading: mutateUserProfileIsLoading } = useMutation(resolver.patchUserProfile, {
onSuccess: () => {
if (refetchUser)
refetchUser();
if (refetchNavigation)
refetchNavigation();
},
});
React.useEffect(() => {
let timer;
if (isSuccessTeamSwitcher && setIsSuccessTeamSwitcher) {
timer = setTimeout(() => {
setIsSuccessTeamSwitcher(false);
}, 3000);
}
return () => clearTimeout(timer);
}, [isSuccessTeamSwitcher, setIsSuccessTeamSwitcher]);
useEffect(() => {
let accountTeams, standardTeams, personalTeam = [];
if (hasUserTeams) {
accountTeams = userTeams?.data?.accountTeams ?? [];
standardTeams = userTeams?.data?.standardTeams ?? [];
personalTeam = userTeams?.data?.personalTeam ?? [];
}
else {
accountTeams = teamsQuery?.data?.accountTeams ?? [];
standardTeams = teamsQuery?.data?.standardTeams ?? [];
personalTeam = teamsQuery?.data?.personalTeam ?? [];
}
const userHasPersonalTeam = personalTeam.length > 0;
const userHasAccountTeams = accountTeams.length > 0;
const userHasStandardTeams = standardTeams.length > 0;
const userHasTeams = userHasPersonalTeam || userHasAccountTeams || userHasStandardTeams;
const handleSelectTeam = async ({ team }) => {
setSelectedTeam(team);
if (!userTeamInstanceSwitcherDefault) {
const body = {
teamInstanceSwitcherDefault: team.id,
};
await mutateUserProfile({ baseServicesUrl, body });
}
};
if (userHasTeams) {
if (!userTeamInstanceSwitcherDefault) {
if (userHasPersonalTeam) {
handleSelectTeam({ team: personalTeam[0] });
}
else if (userHasAccountTeams) {
const sortedAccounts = sortBy(accountTeams, [
(account) => (account.displayName ? account.displayName : account.name),
]);
handleSelectTeam({ team: sortedAccounts[0] });
}
else if (userHasStandardTeams) {
const sortedStandardTeams = sortBy(standardTeams, [
(standardTeam) => (standardTeam.displayName ? standardTeam.displayName : standardTeam.name),
]);
handleSelectTeam({ team: sortedStandardTeams[0] });
}
}
else if (selectedTeam?.id !== userTeamInstanceSwitcherDefault) {
let allProjectTeams = [];
if (userHasAccountTeams) {
accountTeams.forEach((team) => {
if (team.projectTeams && team.projectTeams.length > 0) {
allProjectTeams = allProjectTeams.concat(team.projectTeams);
}
});
}
const allTeams = personalTeam.concat(standardTeams, accountTeams, allProjectTeams);
const newSelectedTeam = allTeams.find((team) => team.id === userTeamInstanceSwitcherDefault);
handleSelectTeam({ team: newSelectedTeam });
}
}
}, [
baseServicesUrl,
hasUserTeams,
mutateUserProfile,
selectedTeam,
teamsQuery?.data?.accountTeams,
teamsQuery?.data?.personalTeam,
teamsQuery?.data?.standardTeams,
userTeamInstanceSwitcherDefault,
userTeams?.data?.accountTeams,
userTeams?.data?.personalTeam,
userTeams?.data?.standardTeams,
]);
const handleHeaderMenuClick = () => {
setOpenAccountSubmenuId("");
};
const handleTeamClick = ({ team, type }) => {
setOpenAccountSubmenuId("");
if (analyticsHelpers?.navigateEventHandler && trackEvent) {
analyticsHelpers.navigateEventHandler({
action: `Clicked ${team.name} in Team Switcher`,
category: "Team Switcher",
destinationPath: teamLink({ teamId: team.id }),
teamId: team.id,
teamType: type,
trackEvent,
});
}
if (isLaunchpad && Boolean(history)) {
history.push(`/teams/${team.id}`);
}
else {
window.open(teamLink({ teamId: team.id }), "_self");
}
};
const handleCreateJoinTeamClick = (e) => {
if (analyticsHelpers?.ctaEventHandler && trackEvent) {
analyticsHelpers.ctaEventHandler({
category: "Team Switcher",
CTA: "Create/Join team clicked",
pageName: "",
trackEvent,
});
}
if (createJoinTeamTrigger) {
createJoinTeamTrigger(e);
}
else {
window.open(`${navigationPlatform.baseEnvUrl}/launchpad?createJoinTeam=true`, "_self");
}
};
const handleOpenAccountSubmenu = ({ e, id }) => {
e.stopPropagation();
if (openAccountSubmenuId === id) {
setOpenAccountSubmenuId("");
}
else {
setOpenAccountSubmenuId(id);
}
};
if (userTeams?.isLoading || teamsQuery?.isLoading || mutateUserProfileIsLoading) {
return (React.createElement("div", { style: { display: "flex", alignItems: "center" } },
React.createElement(InlineLoading, null)));
}
if (userTeams?.data || teamsQuery?.data) {
let accountTeams, standardTeams, personalTeam = [];
if (hasUserTeams) {
accountTeams = userTeams?.data?.accountTeams ?? [];
standardTeams = userTeams?.data?.standardTeams ?? [];
personalTeam = userTeams?.data?.personalTeam ?? [];
}
else {
accountTeams = teamsQuery?.data?.accountTeams ?? [];
standardTeams = teamsQuery?.data?.standardTeams ?? [];
personalTeam = teamsQuery?.data?.personalTeam ?? [];
}
let sortedAccountTeamsWithNamesToDisplay = [];
let sortedStandardTeamsWithNamesToDisplay = [];
if (accountTeams?.length > 0) {
const newAccountTeams = accountTeams.map((team) => {
let newProjectTeams = [];
if (team.projectTeams && team.projectTeams.length > 0) {
newProjectTeams = team.projectTeams?.map((team) => ({
...team,
nameToDisplay: team.displayName ? team.displayName : team.name,
}));
}
return {
...team,
nameToDisplay: team.displayName ? team.displayName : team.name,
projectTeams: sortBy(newProjectTeams, ["nameToDisplay"]),
};
});
sortedAccountTeamsWithNamesToDisplay = sortBy(newAccountTeams, ["nameToDisplay"]);
}
if (standardTeams?.length > 0) {
const newStandardTeams = standardTeams.map((team) => {
return {
...team,
nameToDisplay: team.displayName ? team.displayName : team.name,
};
});
sortedStandardTeamsWithNamesToDisplay = sortBy(newStandardTeams, ["nameToDisplay"]);
}
let selectedTeamName = selectedTeam?.displayName ? selectedTeam.displayName : selectedTeam?.name;
if (selectedTeamName && selectedTeamName.length > 65) {
selectedTeamName = selectedTeamName.slice(0, 65) + "...";
}
const isPartnerUser = Boolean(user?.type === USER_PLATFORM_ROLE.Partner);
return (React.createElement("div", { className: headerDropdownMenuContainerClassname },
isLoadingTeamSwitcher ? (React.createElement("div", { className: headerDropdownMenuLoadingClassname },
React.createElement(InlineLoading, null))) : isSuccessTeamSwitcher ? (React.createElement("div", { className: headerDropdownMenuSuccessClassname },
React.createElement(CheckmarkFilled, null))) : null,
React.createElement(HeaderMenu, { id: "header-team-switcher-menu", "aria-label": menuAriaLabelRecord, className: headerDropdownMenuClassname, menuLinkName: selectedTeamName ? selectedTeamName : "No team selected", onClick: handleHeaderMenuClick, "data-testid": "header-team-switcher-menu" },
React.createElement(HeaderMenu$1, { "aria-labelledby": menuButtonId, className: headerDropdownMenuListClassname, id: menuListId },
!isPartnerUser && (React.createElement(HeaderMenuItem, { id: "header-team-switcher-create-join-team-button", className: headerTeamSwitcherCreateTeamButtonContainerClassname, onClick: handleCreateJoinTeamClick,
// eslint-disable-next-line no-script-url
href: "javascript:void(0)", role: "menuitem", "data-testid": "header-team-switcher-create-join-team-button" },
React.createElement("div", { className: headerTeamSwitcherCreateTeamButtonClassname },
React.createElement("span", { className: headerTeamSwitcherCreateTeamButtonTextClassname }, createTeamButtonText),
React.createElement(AddAlt, { className: headerTeamSwitcherCreateTeamButtonIconClassname })))),
personalTeam.length > 0
? personalTeam.map((team) => {
const teamName = team.displayName ? team.displayName : team.name;
const isTeamSelected = team.id === selectedTeam?.id;
return (React.createElement("div", { key: team.id, id: `${team.id}-personal-menu-item-id` },
React.createElement(HeaderMenuItem, { key: team.id, id: `${team.id}-personal-menu-item`, "aria-selected": isTeamSelected, className: headerDropdownMenuItemContainerClassname, onClick: () => {
handleTeamClick({ team, type: "personal" });
},
// eslint-disable-next-line no-script-url
href: "javascript:void(0)", "data-testid": "header-team-switcher-menu-item" },
React.createElement("div", { className: headerDropdownMenuItemClassname },
React.createElement("span", { title: teamName, className: headerDropdownMenuItemTextClassname }, teamName),
isTeamSelected ? React.createElement(CheckmarkFilled, { className: headerDropdownMenuItemIconClassname }) : null))));
})
: null,
accountTeams.length > 0
? sortedAccountTeamsWithNamesToDisplay.map((team) => {
const isSubmenuOpen = team.id === openAccountSubmenuId;
const isProjectTeamSelected = team.projectTeams &&
team.projectTeams.length > 0 &&
team.projectTeams.some((team) => team.id === selectedTeam?.id);
const isTeamSelected = team.id === selectedTeam?.id;
const isMenuSelected = isTeamSelected || isProjectTeamSelected;
return (React.createElement("div", { key: team.id, id: `${team.id}-account-menu` },
React.createElement(HeaderMenuItem, { "aria-expanded": isSubmenuOpen, "aria-selected": isMenuSelected, className: headerDropdownMenuItemAccountContainerClassname, onClick: (e) => handleOpenAccountSubmenu({ e, id: team.id }),
// eslint-disable-next-line no-script-url
href: "javascript:void(0)", "data-testid": "header-team-switcher-menu-account-accordion" },
React.createElement("div", { className: headerDropdownMenuItemAccountClassname },
React.createElement("div", { className: headerDropdownMenuItemTextIconClassname },
React.createElement("span", { title: team.nameToDisplay, className: headerDropdownMenuItemTextClassname }, team.nameToDisplay),
isMenuSelected ? (React.createElement(CheckmarkFilled, { className: headerDropdownMenuItemIconClassname })) : null),
React.createElement("div", { className: headerDropdownMenuItemAccountIconsClassname },
React.createElement(GroupAccount, { className: headerDropdownMenuItemAccountGroupIconClassname }),
React.createElement(ChevronDown, { className: headerDropdownMenuItemAccountChevronIconClassname })))),
React.createElement("div", { id: `${team.id}-account-submenu`, key: `${team.id}-account-submenu`, "aria-expanded": isSubmenuOpen, className: headerDropdownMenuItemAccountSubmenuClassname },
React.createElement(HeaderMenuItem, { key: `${team.id}-menu-item`, id: `${team.id}-account-menu-item`, "aria-selected": isTeamSelected, className: headerDropdownMenuItemContainerClassname, onClick: () => {
handleTeamClick({ team, type: "account" });
}, "data-testid": "header-team-switcher-menu-account-accordion-item",
// eslint-disable-next-line no-script-url
href: "javascript:void(0)" },
React.createElement("div", { className: headerDropdownMenuItemClassname, style: { paddingLeft: "1rem" } },
React.createElement("span", { title: team.nameToDisplay, className: headerDropdownMenuItemTextClassname }, "Account Page"),
isTeamSelected ? (React.createElement(CheckmarkFilled, { className: headerDropdownMenuItemIconClassname })) : null)),
team.projectTeams && team.projectTeams.length > 0
? team.projectTeams.map((team) => {
const isTeamSelected = team.id === selectedTeam?.id;
return (React.createElement("div", { key: team.id, id: `${team.id}-project-menu-item` },
React.createElement(HeaderMenuItem, { "aria-selected": isTeamSelected, className: headerDropdownMenuItemContainerClassname, onClick: () => {
handleTeamClick({ team, type: "project" });
}, "data-testid": "header-team-switcher-menu-account-accordion-item",
// eslint-disable-next-line no-script-url
href: "javascript:void(0)" },
React.createElement("div", { className: headerDropdownMenuItemClassname, style: { paddingLeft: "1rem" } },
React.createElement("span", { title: team.nameToDisplay, className: headerDropdownMenuItemTextClassname }, team.nameToDisplay),
isTeamSelected ? (React.createElement(CheckmarkFilled, { className: headerDropdownMenuItemIconClassname })) : null))));
})
: null)));
})
: null,
standardTeams.length > 0
? sortedStandardTeamsWithNamesToDisplay.map((team) => {
const isTeamSelected = team.id === selectedTeam?.id;
return (React.createElement("div", { key: team.id, id: `${team.id}-standard-menu-item` },
React.createElement(HeaderMenuItem, { "aria-selected": isTeamSelected, className: headerDropdownMenuItemContainerClassname, onClick: () => {
handleTeamClick({ team, type: "standard" });
}, "data-testid": "header-team-switcher-menu-item",
// eslint-disable-next-line no-script-url
href: "javascript:void(0)" },
React.createElement("div", { className: headerDropdownMenuItemClassname },
React.createElement("span", { title: team.nameToDisplay, className: headerDropdownMenuItemTextClassname }, team.nameToDisplay),
isTeamSelected ? React.createElement(CheckmarkFilled, { className: headerDropdownMenuItemIconClassname }) : null))));
})
: null))));
}
return null;
}
export { HeaderTeamSwitcher as default };