/*! * Copyright (c) 2024 PLANKA Software GmbH * Licensed under the Fair Use License: https://github.com/plankanban/planka/blob/master/LICENSE.md */ import React, { useCallback } from 'react'; import classNames from 'classnames'; import { shallowEqual, useDispatch, useSelector } from 'react-redux'; import { Link } from 'react-router'; import { useTranslation } from 'react-i18next'; import { Button, Icon, Menu } from 'semantic-ui-react'; import { Tooltip } from '../../../lib/custom-ui'; import { usePopup } from '../../../lib/popup'; import selectors from '../../../selectors'; import entryActions from '../../../entry-actions'; import Paths from '../../../constants/Paths'; import { BoardMembershipRoles, BoardViews, UserRoles } from '../../../constants/Enums'; import UserAvatar from '../../users/UserAvatar'; import UserActionsStep from '../../users/UserActionsStep'; import NotificationsStep from '../../notifications/NotificationsStep'; import styles from './Header.module.scss'; const POPUP_PROPS = { position: 'bottom right', }; const Header = React.memo(() => { const user = useSelector(selectors.selectCurrentUser); const project = useSelector(selectors.selectCurrentProject); const board = useSelector(selectors.selectCurrentBoard); const notificationIds = useSelector(selectors.selectNotificationIdsForCurrentUser); const isFavoritesEnabled = useSelector(selectors.selectIsFavoritesEnabled); const isEditModeEnabled = useSelector(selectors.selectIsEditModeEnabled); const withFavoritesToggler = useSelector( // TODO: use selector instead? (state) => selectors.selectFavoriteProjectIdsForCurrentUser(state).length > 0, ); const { withEditModeToggler, canEditProject } = useSelector((state) => { if (!project) { return { withEditModeToggler: false, canEditProject: false, }; } const isAdminInSharedProject = user.role === UserRoles.ADMIN && !project.ownerProjectManagerId; const isManager = selectors.selectIsCurrentUserManagerForCurrentProject(state); if (isAdminInSharedProject || isManager) { return { withEditModeToggler: true, canEditProject: isEditModeEnabled, }; } if (!board) { return { withEditModeToggler: false, canEditProject: false, }; } const boardMembership = selectors.selectCurrentUserMembershipForCurrentBoard(state); const isEditor = !!boardMembership && boardMembership.role === BoardMembershipRoles.EDITOR; return { withEditModeToggler: board.view === BoardViews.KANBAN && isEditor, canEditProject: false, }; }, shallowEqual); const dispatch = useDispatch(); const [t] = useTranslation(); const handleToggleFavoritesClick = useCallback(() => { dispatch(entryActions.toggleFavorites(!isFavoritesEnabled)); }, [isFavoritesEnabled, dispatch]); const handleToggleEditModeClick = useCallback(() => { dispatch(entryActions.toggleEditMode(!isEditModeEnabled)); }, [isEditModeEnabled, dispatch]); const handleProjectSettingsClick = useCallback(() => { if (!canEditProject) { return; } dispatch(entryActions.openProjectSettingsModal()); }, [canEditProject, dispatch]); const NotificationsPopup = usePopup(NotificationsStep, POPUP_PROPS); const UserActionsPopup = usePopup(UserActionsStep, POPUP_PROPS); return (
{!project && ( PLANKA )} {project && ( {project.name} {canEditProject && ( )} )} {withFavoritesToggler && ( )} {withEditModeToggler && ( )} {notificationIds.length > 0 && ( {notificationIds.length} )} {user.name}
); }); export default Header;