Merge pull request #1236 from symonbaikov/feat/no-member-filter
Add filter for cards without members ("No member" filter)
Conflicted with the negative label filter, which had added its own field to
the board model next to this one. Both stay; they filter on different things.
This commit is contained in:
@@ -162,6 +162,14 @@ const Filters = React.memo(() => {
|
||||
|
||||
const isSearchActive = search || isSearchFocused;
|
||||
|
||||
const handleNoMemberClick = useCallback(() => {
|
||||
if (board.filterNoMember) {
|
||||
dispatch(entryActions.removeNoMemberFromFilterInCurrentBoard());
|
||||
} else {
|
||||
dispatch(entryActions.setNoMemberToFilterInCurrentBoard());
|
||||
}
|
||||
}, [dispatch, board.filterNoMember]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<span className={styles.filter}>
|
||||
@@ -176,6 +184,13 @@ const Filters = React.memo(() => {
|
||||
{userIds.length === 0 && <span className={styles.filterLabel}>{t('common.all')}</span>}
|
||||
</button>
|
||||
</BoardMembershipsPopup>
|
||||
<button
|
||||
type="button"
|
||||
className={classNames(styles.filterButton, styles.filterLabel)}
|
||||
onClick={handleNoMemberClick}
|
||||
>
|
||||
{t('common.noMember')}
|
||||
</button>
|
||||
{userIds.length === 0 && withCurrentUserSelector && (
|
||||
<Tooltip content={t('action.filterByCurrentUser')}>
|
||||
<button type="button" className={styles.filterButton} onClick={handleCurrentUserSelect}>
|
||||
|
||||
@@ -273,6 +273,9 @@ export default {
|
||||
LABEL_FROM_BOARD_FILTER_REMOVE: 'LABEL_FROM_BOARD_FILTER_REMOVE',
|
||||
LABEL_FILTER_IN_BOARD_UPDATE: 'LABEL_FILTER_IN_BOARD_UPDATE',
|
||||
|
||||
NO_MEMBER_TO_BOARD_FILTER_SET: 'NO_MEMBER_TO_BOARD_FILTER_SET',
|
||||
NO_MEMBER_FROM_BOARD_FILTER_REMOVE: 'NO_MEMBER_FROM_BOARD_FILTER_REMOVE',
|
||||
|
||||
/* Lists */
|
||||
|
||||
LIST_CREATE: 'LIST_CREATE',
|
||||
|
||||
@@ -321,4 +321,9 @@ export default {
|
||||
NOTIFICATION_SERVICE_TEST: `${PREFIX}/NOTIFICATION_SERVICE_TEST`,
|
||||
NOTIFICATION_SERVICE_DELETE: `${PREFIX}/NOTIFICATION_SERVICE_DELETE`,
|
||||
NOTIFICATION_SERVICE_DELETE_HANDLE: `${PREFIX}/NOTIFICATION_SERVICE_DELETE_HANDLE`,
|
||||
|
||||
/* New member types */
|
||||
|
||||
NO_MEMBER_TO_FILTER_IN_CURRENT_BOARD_SET: `${PREFIX}/NO_MEMBER_TO_FILTER_IN_CURRENT_BOARD_SET`,
|
||||
NO_MEMBER_FROM_FILTER_IN_CURRENT_BOARD_REMOVE: `${PREFIX}/NO_MEMBER_FROM_FILTER_IN_CURRENT_BOARD_REMOVE`,
|
||||
};
|
||||
|
||||
@@ -93,6 +93,14 @@ const handleBoardDelete = (board) => ({
|
||||
},
|
||||
});
|
||||
|
||||
const setNoMemberToFilterInCurrentBoard = () => ({
|
||||
type: EntryActionTypes.NO_MEMBER_TO_FILTER_IN_CURRENT_BOARD_SET,
|
||||
});
|
||||
|
||||
const removeNoMemberFromFilterInCurrentBoard = () => ({
|
||||
type: EntryActionTypes.NO_MEMBER_FROM_FILTER_IN_CURRENT_BOARD_REMOVE,
|
||||
});
|
||||
|
||||
export default {
|
||||
createBoardInCurrentProject,
|
||||
handleBoardCreate,
|
||||
@@ -106,4 +114,6 @@ export default {
|
||||
searchInCurrentBoard,
|
||||
deleteBoard,
|
||||
handleBoardDelete,
|
||||
setNoMemberToFilterInCurrentBoard,
|
||||
removeNoMemberFromFilterInCurrentBoard,
|
||||
};
|
||||
|
||||
@@ -312,6 +312,7 @@ export default {
|
||||
noCardsFound: 'No cards found.',
|
||||
noConnectionToServer: 'No connection to server',
|
||||
noLists: 'No lists',
|
||||
noMember: 'No member',
|
||||
noProjects: 'No projects',
|
||||
noUnreadNotifications: 'No unread notifications.',
|
||||
notifications: 'Notifications',
|
||||
|
||||
@@ -69,6 +69,9 @@ export default class extends BaseModel {
|
||||
filterUsers: many('User', 'filterBoards'),
|
||||
filterLabels: many('Label', 'filterBoards'),
|
||||
filterExcludedLabels: many('Label', 'filterExcludedBoards'),
|
||||
filterNoMember: attr({
|
||||
getDefault: () => false,
|
||||
}),
|
||||
};
|
||||
|
||||
static reducer({ type, payload }, Board) {
|
||||
@@ -299,6 +302,17 @@ export default class extends BaseModel {
|
||||
});
|
||||
|
||||
break;
|
||||
case ActionTypes.NO_MEMBER_TO_BOARD_FILTER_SET: {
|
||||
const boardModel = Board.withId(payload.boardId);
|
||||
boardModel.filterUsers.clear();
|
||||
boardModel.update({ filterNoMember: true });
|
||||
break;
|
||||
}
|
||||
case ActionTypes.NO_MEMBER_FROM_BOARD_FILTER_REMOVE: {
|
||||
const boardModel = Board.withId(payload.boardId);
|
||||
boardModel.update({ filterNoMember: false });
|
||||
break;
|
||||
}
|
||||
default:
|
||||
}
|
||||
}
|
||||
@@ -416,6 +430,11 @@ export default class extends BaseModel {
|
||||
cardModels = filterCardLabels(cardModels, filterLabelIds, filterExcludedLabelIds);
|
||||
}
|
||||
|
||||
if (this.filterNoMember) {
|
||||
cardModels = cardModels.filter((cardModel) => cardModel.users.toRefArray().length === 0);
|
||||
return cardModels;
|
||||
}
|
||||
|
||||
return cardModels;
|
||||
}
|
||||
|
||||
|
||||
@@ -389,6 +389,11 @@ export default class extends BaseModel {
|
||||
cardModels = filterCardLabels(cardModels, filterLabelIds, filterExcludedLabelIds);
|
||||
}
|
||||
|
||||
if (this.board.filterNoMember) {
|
||||
cardModels = cardModels.filter((cardModel) => cardModel.users.toRefArray().length === 0);
|
||||
return cardModels;
|
||||
}
|
||||
|
||||
return cardModels;
|
||||
}
|
||||
|
||||
|
||||
@@ -255,6 +255,22 @@ export function* handleBoardDelete(board) {
|
||||
}
|
||||
}
|
||||
|
||||
export function* setNoMemberToFilterInCurrentBoard() {
|
||||
const { boardId } = yield select(selectors.selectPath);
|
||||
yield put({
|
||||
type: ActionTypes.NO_MEMBER_TO_BOARD_FILTER_SET,
|
||||
payload: { boardId },
|
||||
});
|
||||
}
|
||||
|
||||
export function* removeNoMemberFromFilterInCurrentBoard() {
|
||||
const { boardId } = yield select(selectors.selectPath);
|
||||
yield put({
|
||||
type: ActionTypes.NO_MEMBER_FROM_BOARD_FILTER_REMOVE,
|
||||
payload: { boardId },
|
||||
});
|
||||
}
|
||||
|
||||
export default {
|
||||
createBoard,
|
||||
createBoardInCurrentProject,
|
||||
@@ -271,4 +287,6 @@ export default {
|
||||
searchInCurrentBoard,
|
||||
deleteBoard,
|
||||
handleBoardDelete,
|
||||
setNoMemberToFilterInCurrentBoard,
|
||||
removeNoMemberFromFilterInCurrentBoard,
|
||||
};
|
||||
|
||||
@@ -44,5 +44,13 @@ export default function* boardsWatchers() {
|
||||
takeEvery(EntryActionTypes.BOARD_DELETE_HANDLE, ({ payload: { board } }) =>
|
||||
services.handleBoardDelete(board),
|
||||
),
|
||||
takeEvery(
|
||||
EntryActionTypes.NO_MEMBER_TO_FILTER_IN_CURRENT_BOARD_SET,
|
||||
services.setNoMemberToFilterInCurrentBoard,
|
||||
),
|
||||
takeEvery(
|
||||
EntryActionTypes.NO_MEMBER_FROM_FILTER_IN_CURRENT_BOARD_REMOVE,
|
||||
services.removeNoMemberFromFilterInCurrentBoard,
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user