1
0
Fork 0
mirror of https://github.com/plankanban/planka.git synced 2025-07-24 15:49:46 +02:00

fix: Hide label actions based on role

This commit is contained in:
Maksim Eltyshev 2022-11-10 15:28:43 +01:00
parent 0764ca76d3
commit 529309553c
6 changed files with 70 additions and 39 deletions

View file

@ -14,6 +14,7 @@ const BoardActions = React.memo(
filterUsers, filterUsers,
filterLabels, filterLabels,
allUsers, allUsers,
canEdit,
canEditMemberships, canEditMemberships,
onMembershipCreate, onMembershipCreate,
onMembershipUpdate, onMembershipUpdate,
@ -45,6 +46,7 @@ const BoardActions = React.memo(
labels={filterLabels} labels={filterLabels}
allBoardMemberships={memberships} allBoardMemberships={memberships}
allLabels={labels} allLabels={labels}
canEdit={canEdit}
onUserAdd={onUserToFilterAdd} onUserAdd={onUserToFilterAdd}
onUserRemove={onUserFromFilterRemove} onUserRemove={onUserFromFilterRemove}
onLabelAdd={onLabelToFilterAdd} onLabelAdd={onLabelToFilterAdd}
@ -67,6 +69,7 @@ BoardActions.propTypes = {
filterLabels: PropTypes.array.isRequired, filterLabels: PropTypes.array.isRequired,
allUsers: PropTypes.array.isRequired, allUsers: PropTypes.array.isRequired,
/* eslint-enable react/forbid-prop-types */ /* eslint-enable react/forbid-prop-types */
canEdit: PropTypes.bool.isRequired,
canEditMemberships: PropTypes.bool.isRequired, canEditMemberships: PropTypes.bool.isRequired,
onMembershipCreate: PropTypes.func.isRequired, onMembershipCreate: PropTypes.func.isRequired,
onMembershipUpdate: PropTypes.func.isRequired, onMembershipUpdate: PropTypes.func.isRequired,

View file

@ -15,6 +15,7 @@ const Filters = React.memo(
labels, labels,
allBoardMemberships, allBoardMemberships,
allLabels, allLabels,
canEdit,
onUserAdd, onUserAdd,
onUserRemove, onUserRemove,
onLabelAdd, onLabelAdd,
@ -74,6 +75,7 @@ const Filters = React.memo(
title={t('common.filterByLabels', { title={t('common.filterByLabels', {
context: 'title', context: 'title',
})} })}
canEdit={canEdit}
onSelect={onLabelAdd} onSelect={onLabelAdd}
onDeselect={onLabelRemove} onDeselect={onLabelRemove}
onCreate={onLabelCreate} onCreate={onLabelCreate}
@ -108,6 +110,7 @@ Filters.propTypes = {
allBoardMemberships: PropTypes.array.isRequired, allBoardMemberships: PropTypes.array.isRequired,
allLabels: PropTypes.array.isRequired, allLabels: PropTypes.array.isRequired,
/* eslint-enable react/forbid-prop-types */ /* eslint-enable react/forbid-prop-types */
canEdit: PropTypes.bool.isRequired,
onUserAdd: PropTypes.func.isRequired, onUserAdd: PropTypes.func.isRequired,
onUserRemove: PropTypes.func.isRequired, onUserRemove: PropTypes.func.isRequired,
onLabelAdd: PropTypes.func.isRequired, onLabelAdd: PropTypes.func.isRequired,

View file

@ -8,45 +8,51 @@ import { Button } from 'semantic-ui-react';
import styles from './Item.module.scss'; import styles from './Item.module.scss';
import globalStyles from '../../styles.module.scss'; import globalStyles from '../../styles.module.scss';
const Item = React.memo(({ name, color, isPersisted, isActive, onSelect, onDeselect, onEdit }) => { const Item = React.memo(
const handleToggleClick = useCallback(() => { ({ name, color, isPersisted, isActive, canEdit, onSelect, onDeselect, onEdit }) => {
if (isActive) { const handleToggleClick = useCallback(() => {
onDeselect(); if (isActive) {
} else { onDeselect();
onSelect(); } else {
} onSelect();
}, [isActive, onSelect, onDeselect]); }
}, [isActive, onSelect, onDeselect]);
return ( return (
<div className={styles.wrapper}> <div className={styles.wrapper}>
<Button <Button
fluid fluid
content={name} content={name}
active={isActive} active={isActive}
disabled={!isPersisted} disabled={!isPersisted}
className={classNames( className={classNames(
styles.labelButton, styles.labelButton,
isActive && styles.labelButtonActive, isActive && styles.labelButtonActive,
globalStyles[`background${upperFirst(camelCase(color))}`], globalStyles[`background${upperFirst(camelCase(color))}`],
)}
onClick={handleToggleClick}
/>
{canEdit && (
<Button
icon="pencil"
size="small"
floated="right"
disabled={!isPersisted}
className={styles.editButton}
onClick={onEdit}
/>
)} )}
onClick={handleToggleClick} </div>
/> );
<Button },
icon="pencil" );
size="small"
disabled={!isPersisted}
className={styles.editButton}
onClick={onEdit}
/>
</div>
);
});
Item.propTypes = { Item.propTypes = {
name: PropTypes.string, name: PropTypes.string,
color: PropTypes.string.isRequired, color: PropTypes.string.isRequired,
isPersisted: PropTypes.bool.isRequired, isPersisted: PropTypes.bool.isRequired,
isActive: PropTypes.bool.isRequired, isActive: PropTypes.bool.isRequired,
canEdit: PropTypes.bool.isRequired,
onSelect: PropTypes.func.isRequired, onSelect: PropTypes.func.isRequired,
onDeselect: PropTypes.func.isRequired, onDeselect: PropTypes.func.isRequired,
onEdit: PropTypes.func.isRequired, onEdit: PropTypes.func.isRequired,

View file

@ -4,7 +4,6 @@
box-shadow: none; box-shadow: none;
flex: 0 0 auto; flex: 0 0 auto;
font-weight: normal; font-weight: normal;
margin: 0;
padding: 8px 10px; padding: 8px 10px;
text-decoration: underline; text-decoration: underline;
@ -18,6 +17,7 @@
flex: 1 1 auto; flex: 1 1 auto;
font-size: 14px; font-size: 14px;
font-weight: bold; font-weight: bold;
margin-right: 0;
overflow: hidden; overflow: hidden;
padding: 8px 32px 8px 10px; padding: 8px 32px 8px 10px;
position: relative; position: relative;

View file

@ -18,7 +18,18 @@ const StepTypes = {
}; };
const LabelsStep = React.memo( const LabelsStep = React.memo(
({ items, currentIds, title, onSelect, onDeselect, onCreate, onUpdate, onDelete, onBack }) => { ({
items,
currentIds,
title,
canEdit,
onSelect,
onDeselect,
onCreate,
onUpdate,
onDelete,
onBack,
}) => {
const [t] = useTranslation(); const [t] = useTranslation();
const [step, openStep, handleBack] = useSteps(); const [step, openStep, handleBack] = useSteps();
const [search, handleSearchChange] = useField(''); const [search, handleSearchChange] = useField('');
@ -140,6 +151,7 @@ const LabelsStep = React.memo(
color={item.color} color={item.color}
isPersisted={item.isPersisted} isPersisted={item.isPersisted}
isActive={currentIds.includes(item.id)} isActive={currentIds.includes(item.id)}
canEdit={canEdit}
onSelect={() => handleSelect(item.id)} onSelect={() => handleSelect(item.id)}
onDeselect={() => handleDeselect(item.id)} onDeselect={() => handleDeselect(item.id)}
onEdit={() => handleEdit(item.id)} onEdit={() => handleEdit(item.id)}
@ -147,12 +159,14 @@ const LabelsStep = React.memo(
))} ))}
</div> </div>
)} )}
<Button {canEdit && (
fluid <Button
content={t('action.createNewLabel')} fluid
className={styles.addButton} content={t('action.createNewLabel')}
onClick={handleAddClick} className={styles.addButton}
/> onClick={handleAddClick}
/>
)}
</Popup.Content> </Popup.Content>
</> </>
); );
@ -165,6 +179,7 @@ LabelsStep.propTypes = {
currentIds: PropTypes.array.isRequired, currentIds: PropTypes.array.isRequired,
/* eslint-enable react/forbid-prop-types */ /* eslint-enable react/forbid-prop-types */
title: PropTypes.string, title: PropTypes.string,
canEdit: PropTypes.bool,
onSelect: PropTypes.func.isRequired, onSelect: PropTypes.func.isRequired,
onDeselect: PropTypes.func.isRequired, onDeselect: PropTypes.func.isRequired,
onCreate: PropTypes.func.isRequired, onCreate: PropTypes.func.isRequired,
@ -175,6 +190,7 @@ LabelsStep.propTypes = {
LabelsStep.defaultProps = { LabelsStep.defaultProps = {
title: 'common.labels', title: 'common.labels',
canEdit: true,
onBack: undefined, onBack: undefined,
}; };

View file

@ -3,6 +3,7 @@ import { connect } from 'react-redux';
import selectors from '../selectors'; import selectors from '../selectors';
import entryActions from '../entry-actions'; import entryActions from '../entry-actions';
import { BoardMembershipRoles } from '../constants/Enums';
import BoardActions from '../components/BoardActions'; import BoardActions from '../components/BoardActions';
const mapStateToProps = (state) => { const mapStateToProps = (state) => {
@ -12,6 +13,7 @@ const mapStateToProps = (state) => {
const labels = selectors.selectLabelsForCurrentBoard(state); const labels = selectors.selectLabelsForCurrentBoard(state);
const filterUsers = selectors.selectFilterUsersForCurrentBoard(state); const filterUsers = selectors.selectFilterUsersForCurrentBoard(state);
const filterLabels = selectors.selectFilterLabelsForCurrentBoard(state); const filterLabels = selectors.selectFilterLabelsForCurrentBoard(state);
const currentUserMembership = selectors.selectCurrentUserMembershipForCurrentBoard(state);
return { return {
memberships, memberships,
@ -19,6 +21,7 @@ const mapStateToProps = (state) => {
filterUsers, filterUsers,
filterLabels, filterLabels,
allUsers, allUsers,
canEdit: !!currentUserMembership && currentUserMembership.role === BoardMembershipRoles.EDITOR,
canEditMemberships: isCurrentUserManager, canEditMemberships: isCurrentUserManager,
}; };
}; };