import React, { useCallback, useRef, useState } from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; import { useTranslation } from 'react-i18next'; import { Button, Grid, Icon, Modal } from 'semantic-ui-react'; import { usePopup } from '../../lib/popup'; import { Markdown } from '../../lib/custom-ui'; import { startStopwatch, stopStopwatch } from '../../utils/stopwatch'; import NameField from './NameField'; import DescriptionEdit from './DescriptionEdit'; import Tasks from './Tasks'; import Attachments from './Attachments'; import AttachmentAddZone from './AttachmentAddZone'; import AttachmentAddStep from './AttachmentAddStep'; import Activities from './Activities'; import User from '../User'; import Label from '../Label'; import DueDate from '../DueDate'; import Stopwatch from '../Stopwatch'; import BoardMembershipsStep from '../BoardMembershipsStep'; import LabelsStep from '../LabelsStep'; import DueDateEditStep from '../DueDateEditStep'; import StopwatchEditStep from '../StopwatchEditStep'; import CardMoveStep from '../CardMoveStep'; import DeleteStep from '../DeleteStep'; import styles from './CardModal.module.scss'; const CardModal = React.memo( ({ name, description, dueDate, stopwatch, isSubscribed, isActivitiesFetching, isAllActivitiesFetched, isActivitiesDetailsVisible, isActivitiesDetailsFetching, listId, boardId, projectId, users, labels, tasks, attachments, activities, allProjectsToLists, allBoardMemberships, allLabels, canEdit, canEditCommentActivities, canEditAllCommentActivities, onUpdate, onMove, onTransfer, onDuplicate, onDelete, onUserAdd, onUserRemove, onBoardFetch, onLabelAdd, onLabelRemove, onLabelCreate, onLabelUpdate, onLabelMove, onLabelDelete, onTaskCreate, onTaskUpdate, onTaskMove, onTaskDelete, onAttachmentCreate, onAttachmentUpdate, onAttachmentDelete, onActivitiesFetch, onActivitiesDetailsToggle, onCommentActivityCreate, onCommentActivityUpdate, onCommentActivityDelete, onClose, }) => { const [t] = useTranslation(); const [isLinkCopied, setIsLinkCopied] = useState(false); const isGalleryOpened = useRef(false); const handleToggleStopwatchClick = useCallback(() => { onUpdate({ stopwatch: stopwatch.startedAt ? stopStopwatch(stopwatch) : startStopwatch(stopwatch), }); }, [stopwatch, onUpdate]); const handleNameUpdate = useCallback( (newName) => { onUpdate({ name: newName, }); }, [onUpdate], ); const handleDescriptionUpdate = useCallback( (newDescription) => { onUpdate({ description: newDescription, }); }, [onUpdate], ); const handleDueDateUpdate = useCallback( (newDueDate) => { onUpdate({ dueDate: newDueDate, }); }, [onUpdate], ); const handleStopwatchUpdate = useCallback( (newStopwatch) => { onUpdate({ stopwatch: newStopwatch, }); }, [onUpdate], ); const handleCoverUpdate = useCallback( (newCoverAttachmentId) => { onUpdate({ coverAttachmentId: newCoverAttachmentId, }); }, [onUpdate], ); const handleToggleSubscriptionClick = useCallback(() => { onUpdate({ isSubscribed: !isSubscribed, }); }, [isSubscribed, onUpdate]); const handleDuplicateClick = useCallback(() => { onDuplicate(); onClose(); }, [onDuplicate, onClose]); const handleCopyLinkClick = useCallback(() => { navigator.clipboard.writeText(window.location.href); setIsLinkCopied(true); setTimeout(() => { setIsLinkCopied(false); }, 5000); }, []); const handleGalleryOpen = useCallback(() => { isGalleryOpened.current = true; }, []); const handleGalleryClose = useCallback(() => { isGalleryOpened.current = false; }, []); const handleClose = useCallback(() => { if (isGalleryOpened.current) { return; } onClose(); }, [onClose]); const AttachmentAddPopup = usePopup(AttachmentAddStep); const BoardMembershipsPopup = usePopup(BoardMembershipsStep); const LabelsPopup = usePopup(LabelsStep); const DueDateEditPopup = usePopup(DueDateEditStep); const StopwatchEditPopup = usePopup(StopwatchEditStep); const CardMovePopup = usePopup(CardMoveStep); const DeletePopup = usePopup(DeleteStep); const userIds = users.map((user) => user.id); const labelIds = labels.map((label) => label.id); const contentNode = (
{canEdit ? ( ) : (
{name}
)}
{(users.length > 0 || labels.length > 0 || dueDate || stopwatch) && (
{users.length > 0 && (
{t('common.members', { context: 'title', })}
{users.map((user) => ( {canEdit ? ( ) : ( )} ))} {canEdit && ( {/* eslint-disable-next-line jsx-a11y/control-has-associated-label */} )}
)} {labels.length > 0 && (
{t('common.labels', { context: 'title', })}
{labels.map((label) => ( {canEdit ? ( ) : ( ))} {canEdit && ( {/* eslint-disable-next-line jsx-a11y/control-has-associated-label */} )}
)} {dueDate && (
{t('common.dueDate', { context: 'title', })}
{canEdit ? ( ) : ( )}
)} {stopwatch && (
{t('common.stopwatch', { context: 'title', })}
{canEdit ? ( ) : ( )} {canEdit && ( // eslint-disable-next-line jsx-a11y/control-has-associated-label )}
)}
)} {(description || canEdit) && (
{t('common.description')}
{canEdit ? ( {description ? ( ) : ( )} ) : (
{description}
)}
)} {(tasks.length > 0 || canEdit) && (
{t('common.tasks')}
)} {attachments.length > 0 && (
{t('common.attachments')}
)}
{canEdit && (
{t('action.addToCard')}
{t('common.actions')}
)}
); return ( {canEdit ? ( {contentNode} ) : ( contentNode )} ); }, ); CardModal.propTypes = { name: PropTypes.string.isRequired, description: PropTypes.string, dueDate: PropTypes.instanceOf(Date), stopwatch: PropTypes.object, // eslint-disable-line react/forbid-prop-types isSubscribed: PropTypes.bool.isRequired, isActivitiesFetching: PropTypes.bool.isRequired, isAllActivitiesFetched: PropTypes.bool.isRequired, isActivitiesDetailsVisible: PropTypes.bool.isRequired, isActivitiesDetailsFetching: PropTypes.bool.isRequired, listId: PropTypes.string.isRequired, boardId: PropTypes.string.isRequired, projectId: PropTypes.string.isRequired, /* eslint-disable react/forbid-prop-types */ users: PropTypes.array.isRequired, labels: PropTypes.array.isRequired, tasks: PropTypes.array.isRequired, attachments: PropTypes.array.isRequired, activities: PropTypes.array.isRequired, allProjectsToLists: PropTypes.array.isRequired, allBoardMemberships: PropTypes.array.isRequired, allLabels: PropTypes.array.isRequired, /* eslint-enable react/forbid-prop-types */ canEdit: PropTypes.bool.isRequired, canEditCommentActivities: PropTypes.bool.isRequired, canEditAllCommentActivities: PropTypes.bool.isRequired, onUpdate: PropTypes.func.isRequired, onMove: PropTypes.func.isRequired, onTransfer: PropTypes.func.isRequired, onDuplicate: PropTypes.func.isRequired, onDelete: PropTypes.func.isRequired, onUserAdd: PropTypes.func.isRequired, onUserRemove: PropTypes.func.isRequired, onBoardFetch: PropTypes.func.isRequired, onLabelAdd: PropTypes.func.isRequired, onLabelRemove: PropTypes.func.isRequired, onLabelCreate: PropTypes.func.isRequired, onLabelUpdate: PropTypes.func.isRequired, onLabelMove: PropTypes.func.isRequired, onLabelDelete: PropTypes.func.isRequired, onTaskCreate: PropTypes.func.isRequired, onTaskUpdate: PropTypes.func.isRequired, onTaskMove: PropTypes.func.isRequired, onTaskDelete: PropTypes.func.isRequired, onAttachmentCreate: PropTypes.func.isRequired, onAttachmentUpdate: PropTypes.func.isRequired, onAttachmentDelete: PropTypes.func.isRequired, onActivitiesFetch: PropTypes.func.isRequired, onActivitiesDetailsToggle: PropTypes.func.isRequired, onCommentActivityCreate: PropTypes.func.isRequired, onCommentActivityUpdate: PropTypes.func.isRequired, onCommentActivityDelete: PropTypes.func.isRequired, onClose: PropTypes.func.isRequired, }; CardModal.defaultProps = { description: undefined, dueDate: undefined, stopwatch: undefined, }; export default CardModal;