/* * Copyright 2022 Collate. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import { Space, Typography } from 'antd'; import { AxiosError } from 'axios'; import { useGlobalSearchProvider } from 'components/GlobalSearchProvider/GlobalSearchProvider'; import { useTourProvider } from 'components/TourProvider/TourProvider'; import { tabsInfo } from 'constants/explore.constants'; import { urlGitbookDocs, urlGithubRepo, urlJoinSlack, } from 'constants/URL.constants'; import { CurrentTourPageType } from 'enums/tour.enum'; import { isEmpty, isString, max } from 'lodash'; import { observer } from 'mobx-react'; import Qs from 'qs'; import React, { useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { Link, useHistory, useLocation } from 'react-router-dom'; import { toast } from 'react-toastify'; import { getVersion } from 'rest/miscAPI'; import { extractDetailsFromToken } from 'utils/AuthProvider.util'; import { getEntityName } from 'utils/EntityUtils'; import appState from '../../AppState'; import { ReactComponent as IconAPI } from '../../assets/svg/api.svg'; import { ReactComponent as IconDoc } from '../../assets/svg/doc.svg'; import { ReactComponent as IconExternalLink } from '../../assets/svg/external-links.svg'; import { ReactComponent as IconSlackGrey } from '../../assets/svg/slack-grey.svg'; import { ReactComponent as IconVersionBlack } from '../../assets/svg/version-black.svg'; import { getExplorePath, getTeamAndUserDetailsPath, getUserPath, ROUTES, TERM_ADMIN, TERM_USER, TOUR_SEARCH_TERM, } from '../../constants/constants'; import { addToRecentSearched, getNonDeletedTeams, } from '../../utils/CommonUtils'; import SVGIcons, { Icons } from '../../utils/SvgUtils'; import { showErrorToast } from '../../utils/ToastUtils'; import { useAuthContext } from '../authentication/auth-provider/AuthProvider'; import NavBar from '../nav-bar/NavBar'; import './app-bar.style.less'; const Appbar: React.FC = (): JSX.Element => { const location = useLocation(); const history = useHistory(); const { t } = useTranslation(); const { isTourOpen, updateTourPage, updateTourSearch, tourSearchValue } = useTourProvider(); const { isAuthDisabled, isAuthenticated, isProtectedRoute, isTourRoute, onLogoutHandler, } = useAuthContext(); const { searchCriteria } = useGlobalSearchProvider(); const parsedQueryString = Qs.parse( location.search.startsWith('?') ? location.search.substr(1) : location.search ); const searchQuery = isString(parsedQueryString.search) ? parsedQueryString.search : ''; const [searchValue, setSearchValue] = useState(searchQuery); const [isOpen, setIsOpen] = useState(false); const [isFeatureModalOpen, setIsFeatureModalOpen] = useState(false); const [version, setVersion] = useState(''); const handleFeatureModal = (value: boolean) => { setIsFeatureModalOpen(value); }; const handleSearchChange = (value: string) => { setSearchValue(value); if (isTourOpen) { updateTourSearch(value); } else { value ? setIsOpen(true) : setIsOpen(false); } }; const supportLink = [ { label: ( history.push(ROUTES.TOUR)}> {t('label.tour')} ), key: 'tour', }, { label: ( {t('label.doc-plural')} ), key: 'docs', }, { label: ( {t('label.api-uppercase')} ), key: 'api', }, { label: ( {t('label.slack-support')} ), key: 'slack', }, { label: ( handleFeatureModal(true)}> {t('label.whats-new')} ), key: 'whats-new', }, { label: ( {`${t( 'label.version' )} ${(version ? version : '?').split('-')[0]}`} ), key: 'versions', }, ]; const getUsersRoles = (userRoleArr: string[], name: string) => { return (
{name}
{userRoleArr.map((userRole, i) => ( {userRole} ))}
); }; const getUserName = () => { const currentUser = isAuthDisabled ? appState.nonSecureUserDetails : appState.userDetails; return currentUser?.displayName || currentUser?.name || TERM_USER; }; const getUserData = () => { const currentUser = isAuthDisabled ? appState.nonSecureUserDetails : appState.userDetails; const name = currentUser?.displayName || currentUser?.name || TERM_USER; const roles = currentUser?.roles?.map((r) => getEntityName(r)) || []; const inheritedRoles = currentUser?.inheritedRoles?.map((r) => getEntityName(r)) || []; currentUser?.isAdmin && roles.unshift(TERM_ADMIN); const userTeams = getNonDeletedTeams(currentUser?.teams ?? []); const teams = userTeams.splice(0, 3); const remainingTeamsCount = max([userTeams.length, 0]); return (
{' '} {name}
{roles.length > 0 ? getUsersRoles(roles, t('label.role-plural')) : null} {inheritedRoles.length > 0 ? getUsersRoles(inheritedRoles, t('label.inherited-role-plural')) : null} {teams.length > 0 ? (
{t('label.team-plural')} {teams.map((t, i) => ( {t.displayName || t.name} ))} {remainingTeamsCount ? ( {remainingTeamsCount} {t('label.more')} ) : null}
) : null}
); }; const profileDropdown = [ { name: getUserData(), to: '', disabled: false, icon: <>, isText: true, }, ]; const searchHandler = (value: string) => { if (!isTourOpen) { setIsOpen(false); addToRecentSearched(value); const defaultTab: string = searchCriteria !== '' ? tabsInfo[searchCriteria].path : ''; history.push( getExplorePath({ tab: defaultTab, search: value, isPersistFilters: false, }) ); } }; const handleKeyDown = (e: React.KeyboardEvent) => { const target = e.target as HTMLInputElement; if (e.key === 'Enter') { if (isTourOpen && searchValue === TOUR_SEARCH_TERM) { updateTourPage(CurrentTourPageType.EXPLORE_PAGE); updateTourSearch(''); } searchHandler(target.value); } }; const handleOnclick = () => { searchHandler(searchValue); }; const handleClear = () => { setSearchValue(''); searchHandler(''); }; const fetchOMVersion = () => { getVersion() .then((res) => { setVersion(res.version); }) .catch((err: AxiosError) => { showErrorToast( err, t('server.entity-fetch-error', { entity: t('label.version'), }) ); }); }; useEffect(() => { setSearchValue(searchQuery); }, [searchQuery]); useEffect(() => { if (isTourOpen) { setSearchValue(tourSearchValue); } }, [tourSearchValue, isTourOpen]); useEffect(() => { if (isAuthDisabled) { fetchOMVersion(); } else { if (!isEmpty(appState.userDetails)) { fetchOMVersion(); } } }, [appState.userDetails, isAuthDisabled]); useEffect(() => { const handleDocumentVisibilityChange = () => { if ( isProtectedRoute(location.pathname) && isTourRoute(location.pathname) ) { return; } const { isExpired, exp } = extractDetailsFromToken(); if (!document.hidden && isExpired) { exp && toast.info(t('message.session-expired')); onLogoutHandler(); } }; addEventListener('focus', handleDocumentVisibilityChange); return () => { removeEventListener('focus', handleDocumentVisibilityChange); }; }, []); return ( <> {isProtectedRoute(location.pathname) && (isAuthDisabled || isAuthenticated) ? ( ) : null} ); }; export default observer(Appbar);