1
0
Fork 0
mirror of https://github.com/plankanban/planka.git synced 2025-07-19 13:19:44 +02:00

feat: Permissions for board members

Closes #262
This commit is contained in:
Maksim Eltyshev 2022-08-19 14:00:40 +02:00
parent 281cb4a71b
commit f9e0147f33
61 changed files with 1063 additions and 191 deletions

View file

@ -4,89 +4,141 @@ import { useTranslation } from 'react-i18next';
import { withPopup } from '../../../lib/popup';
import { Input, Popup } from '../../../lib/custom-ui';
import { useField } from '../../../hooks';
import { useField, useSteps } from '../../../hooks';
import UserItem from './UserItem';
import styles from './AddPopup.module.scss';
const AddStep = React.memo(({ users, currentUserIds, title, onCreate, onClose }) => {
const [t] = useTranslation();
const [searchValue, handleSearchFieldChange] = useField('');
const search = useMemo(() => searchValue.trim().toLowerCase(), [searchValue]);
const StepTypes = {
SELECT_PERMISSIONS: 'SELECT_PERMISSIONS',
};
const filteredUsers = useMemo(
() =>
users.filter(
(user) =>
user.email.includes(search) ||
user.name.toLowerCase().includes(search) ||
(user.username && user.username.includes(search)),
),
[users, search],
);
const AddStep = React.memo(
({ users, currentUserIds, permissionsSelectStep, title, onCreate, onClose }) => {
const [t] = useTranslation();
const [step, openStep, handleBack] = useSteps();
const [searchValue, handleSearchFieldChange] = useField('');
const search = useMemo(() => searchValue.trim().toLowerCase(), [searchValue]);
const searchField = useRef(null);
const filteredUsers = useMemo(
() =>
users.filter(
(user) =>
user.email.includes(search) ||
user.name.toLowerCase().includes(search) ||
(user.username && user.username.includes(search)),
),
[users, search],
);
const handleUserSelect = useCallback(
(id) => {
onCreate({
userId: id,
});
const searchField = useRef(null);
onClose();
},
[onCreate, onClose],
);
const handleUserSelect = useCallback(
(id) => {
if (permissionsSelectStep) {
openStep(StepTypes.SELECT_PERMISSIONS, {
userId: id,
});
} else {
onCreate({
userId: id,
});
useEffect(() => {
searchField.current.focus();
}, []);
onClose();
}
},
[permissionsSelectStep, onCreate, onClose, openStep],
);
return (
<>
<Popup.Header>
{t(title, {
context: 'title',
})}
</Popup.Header>
<Popup.Content>
<Input
fluid
ref={searchField}
value={searchValue}
placeholder={t('common.searchUsers')}
icon="search"
onChange={handleSearchFieldChange}
/>
{filteredUsers.length > 0 && (
<div className={styles.users}>
{filteredUsers.map((user) => (
<UserItem
key={user.id}
name={user.name}
avatarUrl={user.avatarUrl}
isActive={currentUserIds.includes(user.id)}
onSelect={() => handleUserSelect(user.id)}
const handleRoleSelect = useCallback(
(data) => {
onCreate({
userId: step.params.userId,
...data,
});
onClose();
},
[onCreate, onClose, step],
);
useEffect(() => {
searchField.current.focus();
}, []);
if (step) {
switch (step.type) {
case StepTypes.SELECT_PERMISSIONS: {
const currentUser = users.find((user) => user.id === step.params.userId);
if (currentUser) {
const PermissionsSelectStep = permissionsSelectStep;
return (
<PermissionsSelectStep
buttonContent="action.addMember"
onSelect={handleRoleSelect}
onBack={handleBack}
/>
))}
</div>
)}
</Popup.Content>
</>
);
});
);
}
openStep(null);
break;
}
default:
}
}
return (
<>
<Popup.Header>
{t(title, {
context: 'title',
})}
</Popup.Header>
<Popup.Content>
<Input
fluid
ref={searchField}
value={searchValue}
placeholder={t('common.searchUsers')}
icon="search"
onChange={handleSearchFieldChange}
/>
{filteredUsers.length > 0 && (
<div className={styles.users}>
{filteredUsers.map((user) => (
<UserItem
key={user.id}
name={user.name}
avatarUrl={user.avatarUrl}
isActive={currentUserIds.includes(user.id)}
onSelect={() => handleUserSelect(user.id)}
/>
))}
</div>
)}
</Popup.Content>
</>
);
},
);
AddStep.propTypes = {
/* eslint-disable react/forbid-prop-types */
users: PropTypes.array.isRequired,
currentUserIds: PropTypes.array.isRequired,
/* eslint-disable react/forbid-prop-types */
permissionsSelectStep: PropTypes.elementType,
title: PropTypes.string,
onCreate: PropTypes.func.isRequired,
onClose: PropTypes.func.isRequired,
};
AddStep.defaultProps = {
permissionsSelectStep: undefined,
title: 'common.addMember',
};