/*! * Copyright (c) 2024 PLANKA Software GmbH * Licensed under the Fair Use License: https://github.com/plankanban/planka/blob/master/LICENSE.md */ import React, { useCallback, useMemo } from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; import { shallowEqual, useDispatch, useSelector } from 'react-redux'; import { Icon } from 'semantic-ui-react'; import selectors from '../../../selectors'; import entryActions from '../../../entry-actions'; import { startStopwatch, stopStopwatch } from '../../../utils/stopwatch'; import { isListArchiveOrTrash } from '../../../utils/record-helpers'; import { BoardMembershipRoles, BoardViews, ListTypes } from '../../../constants/Enums'; import TaskList from './TaskList'; import DueDateChip from '../DueDateChip'; import StopwatchChip from '../StopwatchChip'; import UserAvatar from '../../users/UserAvatar'; import LabelChip from '../../labels/LabelChip'; import CustomFieldValueChip from '../../custom-field-values/CustomFieldValueChip'; import styles from './ProjectContent.module.scss'; const ProjectContent = React.memo(({ cardId }) => { const selectCardById = useMemo(() => selectors.makeSelectCardById(), []); const selectListById = useMemo(() => selectors.makeSelectListById(), []); const selectUserIdsByCardId = useMemo(() => selectors.makeSelectUserIdsByCardId(), []); const selectLabelIdsByCardId = useMemo(() => selectors.makeSelectLabelIdsByCardId(), []); const selectShownOnFrontOfCardTaskListIdsByCardId = useMemo( () => selectors.makeSelectShownOnFrontOfCardTaskListIdsByCardId(), [], ); const selectAttachmentsTotalByCardId = useMemo( () => selectors.makeSelectAttachmentsTotalByCardId(), [], ); const selectShownOnFrontOfCardCustomFieldValueIdsByCardId = useMemo( () => selectors.makeSelectShownOnFrontOfCardCustomFieldValueIdsByCardId(), [], ); const selectNotificationsTotalByCardId = useMemo( () => selectors.makeSelectNotificationsTotalByCardId(), [], ); const selectAttachmentById = useMemo(() => selectors.makeSelectAttachmentById(), []); const card = useSelector((state) => selectCardById(state, cardId)); const list = useSelector((state) => selectListById(state, card.listId)); const userIds = useSelector((state) => selectUserIdsByCardId(state, cardId)); const labelIds = useSelector((state) => selectLabelIdsByCardId(state, cardId)); const taskListIds = useSelector((state) => selectShownOnFrontOfCardTaskListIdsByCardId(state, cardId), ); const attachmentsTotal = useSelector((state) => selectAttachmentsTotalByCardId(state, cardId)); const customFieldValueIds = useSelector((state) => selectShownOnFrontOfCardCustomFieldValueIdsByCardId(state, cardId), ); const notificationsTotal = useSelector((state) => selectNotificationsTotalByCardId(state, cardId), ); const coverUrl = useSelector((state) => { const attachment = selectAttachmentById(state, card.coverAttachmentId); return attachment && attachment.data.thumbnailUrls.outside360; }); const { listName, withCreator } = useSelector((state) => { const board = selectors.selectCurrentBoard(state); return { listName: list.name && (board.view === BoardViews.KANBAN ? null : list.name), withCreator: board.alwaysDisplayCardCreator, }; }, shallowEqual); const canEditStopwatch = useSelector((state) => { if (isListArchiveOrTrash(list)) { return false; } const boardMembership = selectors.selectCurrentUserMembershipForCurrentBoard(state); return !!boardMembership && boardMembership.role === BoardMembershipRoles.EDITOR; }); const dispatch = useDispatch(); const handleToggleStopwatchClick = useCallback( (event) => { event.stopPropagation(); dispatch( entryActions.updateCard(cardId, { stopwatch: card.stopwatch.startedAt ? stopStopwatch(card.stopwatch) : startStopwatch(card.stopwatch), }), ); }, [cardId, card.stopwatch, dispatch], ); const hasInformation = card.description || card.dueDate || card.stopwatch || attachmentsTotal > 0 || notificationsTotal > 0 || listName; const isCompact = (labelIds.length === 0 || customFieldValueIds.length === 0) && taskListIds.length === 0 && !hasInformation; const usersNode = userIds.length > 0 || withCreator ? ( {withCreator && ( <> {userIds.length > 0 && } )} {userIds.map((userId) => ( ))} ) : null; return (
{card.name}
{coverUrl && (
)} {labelIds.length > 0 && ( {labelIds.map((labelId) => ( ))} )} {customFieldValueIds.length > 0 && ( {customFieldValueIds.map((customFieldValueId) => ( ))} )} {isCompact && usersNode} {taskListIds.map((taskListId) => ( ))} {hasInformation && ( {notificationsTotal > 0 && ( {notificationsTotal} )} {card.dueDate && ( )} {card.stopwatch && ( )} {listName && ( {listName} )} {card.description && ( )} {attachmentsTotal > 0 && ( {attachmentsTotal} )} )} {!isCompact && usersNode}
); }); ProjectContent.propTypes = { cardId: PropTypes.string.isRequired, }; export default ProjectContent;