diff --git a/client/src/actions/board-memberships.js b/client/src/actions/board-memberships.js index 4871a0a6..41497c2d 100644 --- a/client/src/actions/board-memberships.js +++ b/client/src/actions/board-memberships.js @@ -69,6 +69,36 @@ handleBoardMembershipCreate.fetchProject = (id, currentUserId, currentBoardId) = }, }); +const updateBoardMembership = (id, data) => ({ + type: ActionTypes.BOARD_MEMBERSHIP_UPDATE, + payload: { + id, + data, + }, +}); + +updateBoardMembership.success = (boardMembership) => ({ + type: ActionTypes.BOARD_MEMBERSHIP_UPDATE__SUCCESS, + payload: { + boardMembership, + }, +}); + +updateBoardMembership.failure = (id, error) => ({ + type: ActionTypes.BOARD_MEMBERSHIP_UPDATE__FAILURE, + payload: { + id, + error, + }, +}); + +const handleBoardMembershipUpdate = (boardMembership) => ({ + type: ActionTypes.BOARD_MEMBERSHIP_UPDATE_HANDLE, + payload: { + boardMembership, + }, +}); + const deleteBoardMembership = (id) => ({ type: ActionTypes.BOARD_MEMBERSHIP_DELETE, payload: { @@ -101,6 +131,8 @@ const handleBoardMembershipDelete = (boardMembership) => ({ export default { createBoardMembership, handleBoardMembershipCreate, + updateBoardMembership, + handleBoardMembershipUpdate, deleteBoardMembership, handleBoardMembershipDelete, }; diff --git a/client/src/api/board-memberships.js b/client/src/api/board-memberships.js index 3ef1ce87..d7d3fd64 100644 --- a/client/src/api/board-memberships.js +++ b/client/src/api/board-memberships.js @@ -5,10 +5,14 @@ import socket from './socket'; const createBoardMembership = (boardId, data, headers) => socket.post(`/boards/${boardId}/memberships`, data, headers); +const updateBoardMembership = (id, data, headers) => + socket.patch(`/board-memberships/${id}`, data, headers); + const deleteBoardMembership = (id, headers) => socket.delete(`/board-memberships/${id}`, undefined, headers); export default { createBoardMembership, + updateBoardMembership, deleteBoardMembership, }; diff --git a/client/src/components/BoardActions/BoardActions.jsx b/client/src/components/BoardActions/BoardActions.jsx index 57456290..55e84d54 100644 --- a/client/src/components/BoardActions/BoardActions.jsx +++ b/client/src/components/BoardActions/BoardActions.jsx @@ -3,6 +3,7 @@ import PropTypes from 'prop-types'; import Filters from './Filters'; import Memberships from '../Memberships'; +import BoardMembershipPermissionsSelectStep from '../BoardMembershipPermissionsSelectStep'; import styles from './BoardActions.module.scss'; @@ -15,6 +16,7 @@ const BoardActions = React.memo( allUsers, canEditMemberships, onMembershipCreate, + onMembershipUpdate, onMembershipDelete, onUserToFilterAdd, onUserFromFilterRemove, @@ -30,8 +32,10 @@ const BoardActions = React.memo( @@ -65,6 +69,7 @@ BoardActions.propTypes = { /* eslint-enable react/forbid-prop-types */ canEditMemberships: PropTypes.bool.isRequired, onMembershipCreate: PropTypes.func.isRequired, + onMembershipUpdate: PropTypes.func.isRequired, onMembershipDelete: PropTypes.func.isRequired, onUserToFilterAdd: PropTypes.func.isRequired, onUserFromFilterRemove: PropTypes.func.isRequired, diff --git a/client/src/components/BoardMembershipPermissionsSelectStep/BoardMembershipPermissionsSelectStep.jsx b/client/src/components/BoardMembershipPermissionsSelectStep/BoardMembershipPermissionsSelectStep.jsx new file mode 100644 index 00000000..c68e241e --- /dev/null +++ b/client/src/components/BoardMembershipPermissionsSelectStep/BoardMembershipPermissionsSelectStep.jsx @@ -0,0 +1,101 @@ +import omit from 'lodash/omit'; +import React, { useCallback, useState } from 'react'; +import PropTypes from 'prop-types'; +import { useTranslation } from 'react-i18next'; +import { Button, Form, Menu, Radio, Segment } from 'semantic-ui-react'; +import { Popup } from '../../lib/custom-ui'; + +import { BoardMembershipRoles } from '../../constants/Enums'; + +import styles from './BoardMembershipPermissionsSelectStep.module.scss'; + +const BoardMembershipPermissionsSelectStep = React.memo( + ({ defaultData, title, buttonContent, onSelect, onBack }) => { + const [t] = useTranslation(); + + const [data, setData] = useState(() => ({ + role: BoardMembershipRoles.EDITOR, + canComment: null, + ...defaultData, + })); + + const handleRoleSelectClick = useCallback((role) => { + setData((prevData) => ({ + ...prevData, + role, + canComment: role === BoardMembershipRoles.EDITOR ? null : !!prevData.canComment, + })); + }, []); + + const handleSettingChange = useCallback((_, { name: fieldName, checked: value }) => { + setData((prevData) => ({ + ...prevData, + [fieldName]: value, + })); + }, []); + + const handleSubmit = useCallback(() => { + onSelect(data.role === BoardMembershipRoles.EDITOR ? omit(data, 'canComment') : data); + }, [onSelect, data]); + + return ( + <> + + {t(title, { + context: 'title', + })} + + +
+ + handleRoleSelectClick(BoardMembershipRoles.EDITOR)} + > +
{t('common.editor')}
+
+ {t('common.canEditContentOfBoard')} +
+
+ handleRoleSelectClick(BoardMembershipRoles.VIEWER)} + > +
{t('common.viewer')}
+
{t('common.canOnlyViewBoard')}
+
+
+ {data.role !== BoardMembershipRoles.EDITOR && ( + + + + )} +
- + {canEdit && ( + + + + )} ); }, @@ -141,6 +144,7 @@ Item.propTypes = { createdAt: PropTypes.instanceOf(Date), isCover: PropTypes.bool.isRequired, isPersisted: PropTypes.bool.isRequired, + canEdit: PropTypes.bool.isRequired, onClick: PropTypes.func, onCoverSelect: PropTypes.func.isRequired, onCoverDeselect: PropTypes.func.isRequired, diff --git a/client/src/components/CardModal/CardModal.jsx b/client/src/components/CardModal/CardModal.jsx index 5f386e83..cabdc587 100755 --- a/client/src/components/CardModal/CardModal.jsx +++ b/client/src/components/CardModal/CardModal.jsx @@ -48,6 +48,7 @@ const CardModal = React.memo( allBoardMemberships, allLabels, canEdit, + canEditCommentActivities, canEditAllCommentActivities, onUpdate, onMove, @@ -302,7 +303,10 @@ const CardModal = React.memo( {canEdit ? ( {description ? ( -