Skip to content
Merged
82 changes: 9 additions & 73 deletions apps/meteor/client/NavBarV2/NavBar.tsx
Original file line number Diff line number Diff line change
@@ -1,82 +1,18 @@
import { NavBar as NavBarComponent, NavBarSection, NavBarGroup, NavBarDivider } from '@rocket.chat/fuselage';
import { usePermission, useUser } from '@rocket.chat/ui-contexts';
import { useVoipState } from '@rocket.chat/ui-voip';
import { useTranslation } from 'react-i18next';
import { NavBar as NavBarComponent } from '@rocket.chat/fuselage';
import { useLayout } from '@rocket.chat/ui-contexts';

import NavbarNavigation from './NavBarNavigation';
import {
NavBarItemOmniChannelCallDialPad,
NavBarItemOmnichannelContact,
NavBarItemOmnichannelLivechatToggle,
NavBarItemOmnichannelQueue,
NavBarItemOmnichannelCallToggle,
} from './NavBarOmnichannelToolbar';
import {
NavBarItemMarketPlaceMenu,
NavBarItemDirectoryPage,
NavBarItemHomePage,
NavBarItemCreateNew,
NavBarItemSort,
} from './NavBarPagesToolbar';
import { NavBarItemLoginPage, NavBarItemAdministrationMenu, UserMenu } from './NavBarSettingsToolbar';
import { NavBarItemVoipDialer, NavBarItemVoipToggler } from './NavBarVoipToolbar';
import { useIsCallEnabled, useIsCallReady } from '../contexts/CallContext';
import { useOmnichannelEnabled } from '../hooks/omnichannel/useOmnichannelEnabled';
import { useOmnichannelShowQueueLink } from '../hooks/omnichannel/useOmnichannelShowQueueLink';
import NavBarControlsSection from './NavBarControls/NavBarControlsSection';
import NavBarNavigation from './NavBarNavigation';
import NavBarPagesSection from './NavBarPagesSection';

const NavBar = () => {
const { t } = useTranslation();
const user = useUser();

const showOmnichannel = useOmnichannelEnabled();
const hasManageAppsPermission = usePermission('manage-apps');
const hasAccessMarketplacePermission = usePermission('access-marketplace');
const showMarketplace = hasAccessMarketplacePermission || hasManageAppsPermission;

const showOmnichannelQueueLink = useOmnichannelShowQueueLink();
const isCallEnabled = useIsCallEnabled();
const isCallReady = useIsCallReady();
const { isEnabled: showVoip } = useVoipState();
const { navbar } = useLayout();

return (
<NavBarComponent aria-label='header'>
<NavBarSection>
<NavBarGroup aria-label={t('Pages_and_actions')}>
<NavBarItemHomePage title={t('Home')} />
<NavBarItemDirectoryPage title={t('Directory')} />
{showMarketplace && <NavBarItemMarketPlaceMenu />}
<NavBarItemCreateNew />
<NavBarItemSort />
</NavBarGroup>
</NavBarSection>
<NavbarNavigation />
<NavBarSection>
{showVoip && (
<>
<NavBarGroup aria-label={t('Voice_Call')}>
<NavBarItemVoipDialer primary={isCallEnabled} />
<NavBarItemVoipToggler />
</NavBarGroup>
<NavBarDivider />
</>
)}
{showOmnichannel && (
<>
<NavBarGroup aria-label={t('Omnichannel')}>
{showOmnichannelQueueLink && <NavBarItemOmnichannelQueue title={t('Queue')} />}
{isCallReady && <NavBarItemOmniChannelCallDialPad />}
<NavBarItemOmnichannelContact title={t('Contact_Center')} />
{isCallEnabled && <NavBarItemOmnichannelCallToggle />}
<NavBarItemOmnichannelLivechatToggle />
</NavBarGroup>
<NavBarDivider />
</>
)}
<NavBarGroup aria-label={t('Workspace_and_user_preferences')}>
<NavBarItemAdministrationMenu />
{user ? <UserMenu user={user} /> : <NavBarItemLoginPage />}
</NavBarGroup>
</NavBarSection>
{!navbar.searchExpanded && <NavBarPagesSection />}
<NavBarNavigation />
{!navbar.searchExpanded && <NavBarControlsSection />}
</NavBarComponent>
);
};
Expand Down
49 changes: 49 additions & 0 deletions apps/meteor/client/NavBarV2/NavBarControls/NavBarControlsMenu.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { NavBarItem } from '@rocket.chat/fuselage';
import type { GenericMenuItemProps } from '@rocket.chat/ui-client';
import { GenericMenu } from '@rocket.chat/ui-client';
import { useVoipState } from '@rocket.chat/ui-voip';
import type { HTMLAttributes } from 'react';
import { useTranslation } from 'react-i18next';

import { useOmnichannelEnabled } from '../../hooks/omnichannel/useOmnichannelEnabled';

type NavBarControlsMenuProps = Omit<HTMLAttributes<HTMLElement>, 'is'> & {
voipItems: GenericMenuItemProps[];
omnichannelItems: GenericMenuItemProps[];
isPressed: boolean;
};

const NavBarControlsMenu = ({ voipItems, omnichannelItems, isPressed, ...props }: NavBarControlsMenuProps) => {
const { t } = useTranslation();
const { isEnabled: showVoip } = useVoipState();
const showOmnichannel = useOmnichannelEnabled();

const sections = [
{
title: t('Voice_Call'),
items: showVoip ? voipItems : [],
},
{
title: t('Omnichannel'),
items: showOmnichannel ? omnichannelItems : [],
},
].filter((section) => section.items.length > 0);

if (sections.length === 0) {
return null;
}

return (
<GenericMenu
sections={sections}
title={t('Voice_and_omnichannel')}
is={NavBarItem}
placement='bottom-start'
icon='kebab'
pressed={isPressed}
{...props}
/>
);
};

export default NavBarControlsMenu;
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { NavBarSection, NavBarGroup, NavBarDivider } from '@rocket.chat/fuselage';
import { useUser, useLayout } from '@rocket.chat/ui-contexts';
import { useTranslation } from 'react-i18next';

import NavBarControlsWithData from './NavBarControlsWithData';
import NavBarOmnichannelGroup from '../NavBarOmnichannelGroup';
import { NavBarItemLoginPage, NavBarItemAdministrationMenu, UserMenu } from '../NavBarSettingsToolbar';
import NavBarVoipGroup from '../NavBarVoipGroup';

const NavBarControlsSection = () => {
const { t } = useTranslation();
const user = useUser();

const { isMobile } = useLayout();

if (isMobile) {
return (
<NavBarSection>
<NavBarControlsWithData />
<NavBarDivider />
<NavBarGroup aria-label={t('Workspace_and_user_preferences')}>
<NavBarItemAdministrationMenu />
{user ? <UserMenu user={user} /> : <NavBarItemLoginPage />}
</NavBarGroup>
</NavBarSection>
);
}

return (
<NavBarSection>
<NavBarVoipGroup />
<NavBarOmnichannelGroup />
<NavBarGroup aria-label={t('Workspace_and_user_preferences')}>
<NavBarItemAdministrationMenu />
{user ? <UserMenu user={user} /> : <NavBarItemLoginPage />}
</NavBarGroup>
</NavBarSection>
);
};

export default NavBarControlsSection;
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import type { GenericMenuItemProps } from '@rocket.chat/ui-client';
import type { HTMLAttributes } from 'react';

import NavBarControlsMenu from './NavBarControlsMenu';
import { useOmnichannelCallDialPadAction } from '../NavBarOmnichannelGroup/hooks/useOmnichannelCallDialPadAction';
import { useOmnichannelCallToggleAction } from '../NavBarOmnichannelGroup/hooks/useOmnichannelCallToggleAction';

type NavBarControlsMenuProps = Omit<HTMLAttributes<HTMLElement>, 'is'> & {
voipItems: GenericMenuItemProps[];
omnichannelItems: GenericMenuItemProps[];
isPressed: boolean;
};

const NavBarControlsWithCall = ({ voipItems, omnichannelItems, isPressed, ...props }: NavBarControlsMenuProps) => {
const {
icon: omnichannelCallIcon,
title: omnichannelCallTitle,
handleOpenDialModal,
isDisabled: callDialPadDisabled,
} = useOmnichannelCallDialPadAction();

const {
title: omnichannelCallTogglerTitle,
icon: omnichannelCallTogglerIcon,
handleToggleCall,
isDisabled: callTogglerDisabled,
} = useOmnichannelCallToggleAction();

const omnichannelItemsWithCall = [
...omnichannelItems,
{
id: 'omnichannelCallDialPad',
icon: omnichannelCallIcon,
content: omnichannelCallTitle,
onClick: handleOpenDialModal,
disabled: callDialPadDisabled,
},
{
id: 'omnichannelCallToggler',
icon: omnichannelCallTogglerIcon,
content: omnichannelCallTogglerTitle,
onClick: handleToggleCall,
disabled: callTogglerDisabled,
},
] as GenericMenuItemProps[];

return <NavBarControlsMenu voipItems={voipItems} omnichannelItems={omnichannelItemsWithCall} isPressed={isPressed} {...props} />;
};

export default NavBarControlsWithCall;
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import type { GenericMenuItemProps } from '@rocket.chat/ui-client';
import type { HTMLAttributes } from 'react';

import NavBarControlsMenu from './NavBarControlsMenu';
import NavbarControlsWithCall from './NavBarControlsWithCall';
import { useIsCallEnabled } from '../../contexts/CallContext';
import { useOmnichannelContactAction } from '../NavBarOmnichannelGroup/hooks/useOmnichannelContactAction';
import { useOmnichannelLivechatToggle } from '../NavBarOmnichannelGroup/hooks/useOmnichannelLivechatToggle';
import { useOmnichannelQueueAction } from '../NavBarOmnichannelGroup/hooks/useOmnichannelQueueAction';
import { useVoipDialerAction } from '../NavBarVoipGroup/hooks/useVoipDialerAction';
import { useVoipTogglerAction } from '../NavBarVoipGroup/hooks/useVoipTogglerAction';

type NavBarControlsMenuProps = Omit<HTMLAttributes<HTMLElement>, 'is'>;

const NavBarControlsWithData = (props: NavBarControlsMenuProps) => {
const isCallEnabled = useIsCallEnabled();

const { title: dialerTitle, handleToggleDialer, isPressed: isVoipDialerPressed, isDisabled: dialerDisabled } = useVoipDialerAction();
const { isRegistered, title: togglerTitle, handleToggleVoip, isDisabled: togglerDisabled } = useVoipTogglerAction();

const {
isEnabled: queueEnabled,
icon: queueIcon,
title: queueTitle,
handleGoToQueue,
isPressed: isQueuePressed,
} = useOmnichannelQueueAction();

const {
title: contactCenterTitle,
icon: contactCenterIcon,
handleGoToContactCenter,
isPressed: isContactPressed,
} = useOmnichannelContactAction();

const {
title: omnichannelLivechatTogglerTitle,
icon: omnichannelLivechatTogglerIcon,
handleAvailableStatusChange,
} = useOmnichannelLivechatToggle();

const voipItems = [
{
id: 'voipDialer',
icon: 'dialpad',
content: dialerTitle,
onClick: handleToggleDialer,
disabled: dialerDisabled,
},
{
id: 'voipToggler',
icon: isRegistered ? 'phone-disabled' : 'phone',
content: togglerTitle,
onClick: handleToggleVoip,
disabled: togglerDisabled,
},
].filter(Boolean) as GenericMenuItemProps[];

const omnichannelItems = [
queueEnabled && {
id: 'omnichannelQueue',
icon: queueIcon,
content: queueTitle,
onClick: handleGoToQueue,
disabled: dialerDisabled,
},
{
id: 'omnichannelContact',
icon: contactCenterIcon,
content: contactCenterTitle,
onClick: handleGoToContactCenter,
},
{
id: 'omnichannelLivechatToggler',
icon: omnichannelLivechatTogglerIcon,
content: omnichannelLivechatTogglerTitle,
onClick: handleAvailableStatusChange,
},
].filter(Boolean) as GenericMenuItemProps[];

const isPressed = isVoipDialerPressed || isQueuePressed || isContactPressed;

if (isCallEnabled) {
return <NavbarControlsWithCall voipItems={voipItems} omnichannelItems={omnichannelItems} isPressed={isPressed} {...props} />;
}

return <NavBarControlsMenu voipItems={voipItems} omnichannelItems={omnichannelItems} isPressed={isPressed} {...props} />;
};

export default NavBarControlsWithData;
19 changes: 11 additions & 8 deletions apps/meteor/client/NavBarV2/NavBarNavigation.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { NavBarGroup, NavBarSection, NavBarItem } from '@rocket.chat/fuselage';
import { useRouter } from '@rocket.chat/ui-contexts';
import { NavBarGroup, NavBarItem, Box } from '@rocket.chat/fuselage';
import { useLayout, useRouter } from '@rocket.chat/ui-contexts';
import { FocusScope } from 'react-aria';
import { useTranslation } from 'react-i18next';

Expand All @@ -8,17 +8,20 @@ import NavBarSearch from './NavBarSearch';
const NavbarNavigation = () => {
const { t } = useTranslation();
const { navigate } = useRouter();
const { isMobile } = useLayout();

return (
<NavBarSection>
<Box display='flex' flexGrow={1} justifyContent='center'>
<FocusScope>
<NavBarSearch />
</FocusScope>
<NavBarGroup aria-label={t('History_navigation')}>
<NavBarItem title={t('Back_in_history')} onClick={() => navigate(-1)} icon='chevron-right' small />
<NavBarItem title={t('Forward_in_history')} onClick={() => navigate(1)} icon='chevron-left' small />
</NavBarGroup>
</NavBarSection>
{!isMobile && (
<NavBarGroup aria-label={t('History_navigation')}>
<NavBarItem title={t('Back_in_history')} onClick={() => navigate(-1)} icon='chevron-right' small />
<NavBarItem title={t('Forward_in_history')} onClick={() => navigate(1)} icon='chevron-left' small />
</NavBarGroup>
)}
</Box>
);
};

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { NavBarItem } from '@rocket.chat/fuselage';
import type { ComponentPropsWithoutRef } from 'react';
import { useTranslation } from 'react-i18next';

import { useOmnichannelCallDialPadAction } from './hooks/useOmnichannelCallDialPadAction';

type NavBarItemOmniChannelCallDialPadProps = ComponentPropsWithoutRef<typeof NavBarItem>;

const NavBarItemOmniChannelCallDialPad = (props: NavBarItemOmniChannelCallDialPadProps) => {
const { t } = useTranslation();

const { title, icon, handleOpenDialModal, isDisabled } = useOmnichannelCallDialPadAction();

return (
<NavBarItem icon={icon} onClick={handleOpenDialModal} disabled={isDisabled} aria-label={t('Open_Dialpad')} title={title} {...props} />
);
};

export default NavBarItemOmniChannelCallDialPad;
Loading
Loading