/*!
* 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 { shallowEqual, useDispatch, useSelector } from 'react-redux';
import { useTranslation } from 'react-i18next';
import { Menu } from 'semantic-ui-react';
import { Popup } from '../../../lib/custom-ui';
import selectors from '../../../selectors';
import entryActions from '../../../entry-actions';
import { useSteps } from '../../../hooks';
import { isListArchiveOrTrash } from '../../../utils/record-helpers';
import { BoardMembershipRoles, CardTypes, ListTypes } from '../../../constants/Enums';
import SelectCardTypeStep from '../SelectCardTypeStep';
import EditDueDateStep from '../EditDueDateStep';
import EditStopwatchStep from '../EditStopwatchStep';
import MoveCardStep from '../MoveCardStep';
import ConfirmationStep from '../../common/ConfirmationStep';
import BoardMembershipsStep from '../../board-memberships/BoardMembershipsStep';
import LabelsStep from '../../labels/LabelsStep';
import styles from './ActionsStep.module.scss';
const StepTypes = {
EDIT_TYPE: 'EDIT_TYPE',
USERS: 'USERS',
LABELS: 'LABELS',
EDIT_DUE_DATE: 'EDIT_DUE_DATE',
EDIT_STOPWATCH: 'EDIT_STOPWATCH',
MOVE: 'MOVE',
ARCHIVE: 'ARCHIVE',
DELETE: 'DELETE',
};
const ActionsStep = React.memo(({ cardId, onNameEdit, onClose }) => {
const selectCardById = useMemo(() => selectors.makeSelectCardById(), []);
const selectListById = useMemo(() => selectors.makeSelectListById(), []);
const selectPrevListById = useMemo(() => selectors.makeSelectListById(), []);
const selectUserIdsByCardId = useMemo(() => selectors.makeSelectUserIdsByCardId(), []);
const selectLabelIdsByCardId = useMemo(() => selectors.makeSelectLabelIdsByCardId(), []);
const board = useSelector(selectors.selectCurrentBoard);
const card = useSelector((state) => selectCardById(state, cardId));
const list = useSelector((state) => selectListById(state, card.listId));
// TODO: check availability?
const prevList = useSelector(
(state) => card.prevListId && selectPrevListById(state, card.prevListId),
);
const userIds = useSelector((state) => selectUserIdsByCardId(state, cardId));
const labelIds = useSelector((state) => selectLabelIdsByCardId(state, cardId));
const {
canEditType,
canEditName,
canEditDueDate,
canEditStopwatch,
canDuplicate,
canMove,
canRestore,
canArchive,
canDelete,
canUseMembers,
canUseLabels,
} = useSelector((state) => {
const boardMembership = selectors.selectCurrentUserMembershipForCurrentBoard(state);
const isEditor = !!boardMembership && boardMembership.role === BoardMembershipRoles.EDITOR;
if (isListArchiveOrTrash(list)) {
return {
canEditType: false,
canEditName: false,
canEditDueDate: false,
canEditStopwatch: false,
canDuplicate: false,
canMove: false,
canRestore: isEditor,
canArchive: isEditor,
canDelete: isEditor,
canUseMembers: false,
canUseLabels: false,
};
}
return {
canEditType: isEditor,
canEditName: isEditor,
canEditDueDate: isEditor,
canEditStopwatch: isEditor,
canDuplicate: isEditor,
canMove: isEditor,
canRestore: null,
canArchive: isEditor,
canDelete: isEditor,
canUseMembers: isEditor,
canUseLabels: isEditor,
};
}, shallowEqual);
const dispatch = useDispatch();
const [t] = useTranslation();
const [step, openStep, handleBack] = useSteps();
const handleTypeSelect = useCallback(
(type) => {
dispatch(
entryActions.updateCard(cardId, {
type,
}),
);
},
[cardId, dispatch],
);
const handleDuplicateClick = useCallback(() => {
dispatch(
entryActions.duplicateCard(cardId, {
name: `${card.name} (${t('common.copy', {
context: 'inline',
})})`,
}),
);
onClose();
}, [cardId, onClose, card.name, dispatch, t]);
const handleRestoreClick = useCallback(() => {
dispatch(entryActions.moveCard(cardId, card.prevListId, undefined, true));
}, [cardId, card.prevListId, dispatch]);
const handleArchiveConfirm = useCallback(() => {
dispatch(entryActions.moveCardToArchive(cardId));
}, [cardId, dispatch]);
const isInTrashList = list.type === ListTypes.TRASH;
const handleDeleteConfirm = useCallback(() => {
if (isInTrashList) {
dispatch(entryActions.deleteCard(cardId));
} else {
dispatch(entryActions.moveCardToTrash(cardId));
}
}, [cardId, isInTrashList, dispatch]);
const handleUserSelect = useCallback(
(userId) => {
dispatch(entryActions.addUserToCard(userId, cardId));
},
[cardId, dispatch],
);
const handleUserDeselect = useCallback(
(userId) => {
dispatch(entryActions.removeUserFromCard(userId, cardId));
},
[cardId, dispatch],
);
const handleLabelSelect = useCallback(
(labelId) => {
dispatch(entryActions.addLabelToCard(labelId, cardId));
},
[cardId, dispatch],
);
const handleLabelDeselect = useCallback(
(labelId) => {
dispatch(entryActions.removeLabelFromCard(labelId, cardId));
},
[cardId, dispatch],
);
const handleEditNameClick = useCallback(() => {
onNameEdit();
onClose();
}, [onNameEdit, onClose]);
const handleEditTypeClick = useCallback(() => {
openStep(StepTypes.EDIT_TYPE);
}, [openStep]);
const handleUsersClick = useCallback(() => {
openStep(StepTypes.USERS);
}, [openStep]);
const handleLabelsClick = useCallback(() => {
openStep(StepTypes.LABELS);
}, [openStep]);
const handleEditDueDateClick = useCallback(() => {
openStep(StepTypes.EDIT_DUE_DATE);
}, [openStep]);
const handleEditStopwatchClick = useCallback(() => {
openStep(StepTypes.EDIT_STOPWATCH);
}, [openStep]);
const handleMoveClick = useCallback(() => {
openStep(StepTypes.MOVE);
}, [openStep]);
const handleArchiveClick = useCallback(() => {
openStep(StepTypes.ARCHIVE);
}, [openStep]);
const handleDeleteClick = useCallback(() => {
openStep(StepTypes.DELETE);
}, [openStep]);
if (step) {
switch (step.type) {
case StepTypes.EDIT_TYPE:
return (
);
case StepTypes.USERS:
return (
);
case StepTypes.LABELS:
return (
);
case StepTypes.EDIT_DUE_DATE:
return ;
case StepTypes.EDIT_STOPWATCH:
return ;
case StepTypes.MOVE:
return ;
case StepTypes.ARCHIVE:
return (
);
case StepTypes.DELETE:
return (
);
default:
}
}
return (
<>
{t('common.cardActions', {
context: 'title',
})}
>
);
});
ActionsStep.propTypes = {
cardId: PropTypes.string.isRequired,
onNameEdit: PropTypes.func.isRequired,
onClose: PropTypes.func.isRequired,
};
export default ActionsStep;