UNPKG

@boomerang-io/carbon-addons-boomerang-react

Version:
366 lines (363 loc) 22.9 kB
import React, { useState, useEffect } from 'react'; import { useMutation } from '@tanstack/react-query'; import { InlineLoading, HeaderMenu, HeaderMenuItem } from '@carbon/react'; import { CheckmarkFilled, ChevronDown, AddAlt, GroupAccount } 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'; import { TEAM_TYPES } from '../../constants/TeamTypes.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 headerDropdownMenuContentClassname = `${prefix}--header-dropdown-menu-content`; const headerDropdownMenuContentTextClassname = `${prefix}--header-dropdown-menu-content-text`; const headerDropdownMenuContentIconClassname = `${prefix}--header-dropdown-menu-content-icon`; 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, isPending: mutateUserProfileIsLoading } = useMutation({ mutationFn: 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 }); } }; const handleNoTeamsToSelect = async () => { const body = { teamInstanceSwitcherDefault: null, }; 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 }); } // if teams data loaded but there are no teams } else if (Boolean(userTeamInstanceSwitcherDefault) && ((hasUserTeams && userTeams?.data?.accountTeams?.length === 0 && userTeams?.data?.standardTeams?.length === 0 && userTeams?.data?.personalTeam?.length === 0) || (!hasUserTeams && teamsQuery?.data?.accountTeams?.length === 0 && teamsQuery?.data?.standardTeams?.length === 0 && teamsQuery?.data?.personalTeam?.length === 0))) { handleNoTeamsToSelect(); } else if (userTeamInstanceSwitcherDefault === null) { setSelectedTeam(null); } }, [ 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 newPersonalTeam = personalTeam.length > 0 ? personalTeam.map((personalTeam) => ({ ...personalTeam, type: TEAM_TYPES.PERSONAL, nameToDisplay: personalTeam.displayName ? personalTeam.displayName : personalTeam.name, })) : []; let newAccountTeams = []; let newStandardTeams = []; if (accountTeams?.length > 0) { newAccountTeams = accountTeams.map((team) => { let newProjectTeams = []; if (team.projectTeams && team.projectTeams.length > 0) { newProjectTeams = team.projectTeams?.map((projectTeam) => { return { ...projectTeam, nameToDisplay: projectTeam.displayName ? projectTeam.displayName : projectTeam.name, }; }); } return { ...team, nameToDisplay: team.displayName ? team.displayName : team.name, type: TEAM_TYPES.ACCOUNT, projectTeams: sortBy(newProjectTeams, ["nameToDisplay"]), }; }); } if (standardTeams?.length > 0) { newStandardTeams = standardTeams.map((team) => { return { ...team, type: TEAM_TYPES.STANDARD, nameToDisplay: team.displayName ? team.displayName : team.name, }; }); } let allTeams = newPersonalTeam.concat(newAccountTeams, newStandardTeams); const order = { [TEAM_TYPES.PERSONAL]: 1, [TEAM_TYPES.ACCOUNT]: 2, [TEAM_TYPES.STANDARD]: 3 }; allTeams = sortBy(allTeams, [(team) => order[team.type], "nameToDisplay"]); if (selectedTeam) { const selectedTeamIndex = allTeams.findIndex((team, index) => { if (team.id === selectedTeam.id) { return true; } else if (Array.isArray(team.projectTeams) && team.projectTeams?.length > 0) { return team.projectTeams.some((projectTeam) => projectTeam.id === selectedTeam.id); } return false; }); const [removedTeam] = allTeams.splice(selectedTeamIndex, 1); allTeams.unshift(removedTeam); } let selectedTeamName = selectedTeam?.displayName ? selectedTeam.displayName : selectedTeam?.name ? selectedTeam?.name : "No team selected"; 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, renderMenuContent: () => (React.createElement("div", { className: headerDropdownMenuContentClassname }, React.createElement("p", { title: selectedTeamName, className: headerDropdownMenuContentTextClassname }, selectedTeamName), React.createElement(ChevronDown, { className: headerDropdownMenuContentIconClassname }))), 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 })))), allTeams.map((team) => { if (Boolean(team?.id)) { const isTeamSelected = team.id === selectedTeam?.id; if (team.type === TEAM_TYPES.ACCOUNT) { const isSubmenuOpen = team.id === openAccountSubmenuId; const projectTeams = team.projectTeams; const existProjectTeams = Array.isArray(projectTeams) && projectTeams.length > 0; let selectedProjectTeamIndex = -1; if (existProjectTeams) { selectedProjectTeamIndex = projectTeams.findIndex((team) => team.id === selectedTeam?.id); } const isProjectTeamSelected = selectedProjectTeamIndex >= 0; const isMenuSelected = isTeamSelected || isProjectTeamSelected; if (existProjectTeams && isProjectTeamSelected) { const [removedTeam] = projectTeams.splice(selectedProjectTeamIndex, 1); projectTeams.unshift(removedTeam); } 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)), projectTeams && projectTeams.length > 0 ? 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))); } else { return (React.createElement("div", { key: team.id, id: `${team.id}-${team.type}-menu-item` }, React.createElement(HeaderMenuItem, { "aria-selected": isTeamSelected, className: headerDropdownMenuItemContainerClassname, onClick: () => { handleTeamClick({ team, type: team.type ?? "" }); }, "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)))); } } return null; }))))); } return null; } export { HeaderTeamSwitcher as default };