mirror of
https://github.com/plankanban/planka.git
synced 2025-07-18 20:59:44 +02:00
feat: add 'No member' filter for board cards
This commit is contained in:
parent
e1efe663a0
commit
334f7b2028
9 changed files with 84 additions and 0 deletions
|
@ -147,6 +147,14 @@ const Filters = React.memo(() => {
|
||||||
|
|
||||||
const isSearchActive = search || isSearchFocused;
|
const isSearchActive = search || isSearchFocused;
|
||||||
|
|
||||||
|
const handleNoMemberClick = useCallback(() => {
|
||||||
|
if (board.filterNoMember) {
|
||||||
|
dispatch(entryActions.removeNoMemberFromFilterInCurrentBoard());
|
||||||
|
} else {
|
||||||
|
dispatch(entryActions.setNoMemberToFilterInCurrentBoard());
|
||||||
|
}
|
||||||
|
}, [dispatch, board.filterNoMember]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<span className={styles.filter}>
|
<span className={styles.filter}>
|
||||||
|
@ -161,6 +169,13 @@ const Filters = React.memo(() => {
|
||||||
{userIds.length === 0 && <span className={styles.filterLabel}>{t('common.all')}</span>}
|
{userIds.length === 0 && <span className={styles.filterLabel}>{t('common.all')}</span>}
|
||||||
</button>
|
</button>
|
||||||
</BoardMembershipsPopup>
|
</BoardMembershipsPopup>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className={classNames(styles.filterButton, styles.filterLabel)}
|
||||||
|
onClick={handleNoMemberClick}
|
||||||
|
>
|
||||||
|
{t('common.noMember')}
|
||||||
|
</button>
|
||||||
{userIds.length === 0 && withCurrentUserSelector && (
|
{userIds.length === 0 && withCurrentUserSelector && (
|
||||||
<button type="button" className={styles.filterButton} onClick={handleCurrentUserSelect}>
|
<button type="button" className={styles.filterButton} onClick={handleCurrentUserSelect}>
|
||||||
<span className={styles.filterLabel}>
|
<span className={styles.filterLabel}>
|
||||||
|
|
|
@ -201,6 +201,9 @@ export default {
|
||||||
LABEL_TO_BOARD_FILTER_ADD: 'LABEL_TO_BOARD_FILTER_ADD',
|
LABEL_TO_BOARD_FILTER_ADD: 'LABEL_TO_BOARD_FILTER_ADD',
|
||||||
LABEL_FROM_BOARD_FILTER_REMOVE: 'LABEL_FROM_BOARD_FILTER_REMOVE',
|
LABEL_FROM_BOARD_FILTER_REMOVE: 'LABEL_FROM_BOARD_FILTER_REMOVE',
|
||||||
|
|
||||||
|
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 */
|
/* Lists */
|
||||||
|
|
||||||
LIST_CREATE: 'LIST_CREATE',
|
LIST_CREATE: 'LIST_CREATE',
|
||||||
|
|
|
@ -276,4 +276,9 @@ export default {
|
||||||
NOTIFICATION_SERVICE_TEST: `${PREFIX}/NOTIFICATION_SERVICE_TEST`,
|
NOTIFICATION_SERVICE_TEST: `${PREFIX}/NOTIFICATION_SERVICE_TEST`,
|
||||||
NOTIFICATION_SERVICE_DELETE: `${PREFIX}/NOTIFICATION_SERVICE_DELETE`,
|
NOTIFICATION_SERVICE_DELETE: `${PREFIX}/NOTIFICATION_SERVICE_DELETE`,
|
||||||
NOTIFICATION_SERVICE_DELETE_HANDLE: `${PREFIX}/NOTIFICATION_SERVICE_DELETE_HANDLE`,
|
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 {
|
export default {
|
||||||
createBoardInCurrentProject,
|
createBoardInCurrentProject,
|
||||||
handleBoardCreate,
|
handleBoardCreate,
|
||||||
|
@ -106,4 +114,6 @@ export default {
|
||||||
searchInCurrentBoard,
|
searchInCurrentBoard,
|
||||||
deleteBoard,
|
deleteBoard,
|
||||||
handleBoardDelete,
|
handleBoardDelete,
|
||||||
|
setNoMemberToFilterInCurrentBoard,
|
||||||
|
removeNoMemberFromFilterInCurrentBoard,
|
||||||
};
|
};
|
||||||
|
|
|
@ -215,6 +215,7 @@ export default {
|
||||||
noBoards: 'No boards',
|
noBoards: 'No boards',
|
||||||
noConnectionToServer: 'No connection to server',
|
noConnectionToServer: 'No connection to server',
|
||||||
noLists: 'No lists',
|
noLists: 'No lists',
|
||||||
|
noMember: 'No member',
|
||||||
noProjects: 'No projects',
|
noProjects: 'No projects',
|
||||||
noUnreadNotifications: 'No unread notifications.',
|
noUnreadNotifications: 'No unread notifications.',
|
||||||
notifications: 'Notifications',
|
notifications: 'Notifications',
|
||||||
|
|
|
@ -61,6 +61,9 @@ export default class extends BaseModel {
|
||||||
}),
|
}),
|
||||||
filterUsers: many('User', 'filterBoards'),
|
filterUsers: many('User', 'filterBoards'),
|
||||||
filterLabels: many('Label', 'filterBoards'),
|
filterLabels: many('Label', 'filterBoards'),
|
||||||
|
filterNoMember: attr({
|
||||||
|
getDefault: () => false,
|
||||||
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
static reducer({ type, payload }, Board) {
|
static reducer({ type, payload }, Board) {
|
||||||
|
@ -268,6 +271,17 @@ export default class extends BaseModel {
|
||||||
});
|
});
|
||||||
|
|
||||||
break;
|
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:
|
default:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -374,6 +388,11 @@ export default class extends BaseModel {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.filterNoMember) {
|
||||||
|
cardModels = cardModels.filter((cardModel) => cardModel.users.toRefArray().length === 0);
|
||||||
|
return cardModels;
|
||||||
|
}
|
||||||
|
|
||||||
return cardModels;
|
return cardModels;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -293,6 +293,11 @@ export default class extends BaseModel {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.board.filterNoMember) {
|
||||||
|
cardModels = cardModels.filter((cardModel) => cardModel.users.toRefArray().length === 0);
|
||||||
|
return cardModels;
|
||||||
|
}
|
||||||
|
|
||||||
return cardModels;
|
return cardModels;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -245,6 +245,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 {
|
export default {
|
||||||
createBoard,
|
createBoard,
|
||||||
createBoardInCurrentProject,
|
createBoardInCurrentProject,
|
||||||
|
@ -261,4 +277,6 @@ export default {
|
||||||
searchInCurrentBoard,
|
searchInCurrentBoard,
|
||||||
deleteBoard,
|
deleteBoard,
|
||||||
handleBoardDelete,
|
handleBoardDelete,
|
||||||
|
setNoMemberToFilterInCurrentBoard,
|
||||||
|
removeNoMemberFromFilterInCurrentBoard,
|
||||||
};
|
};
|
||||||
|
|
|
@ -44,5 +44,13 @@ export default function* boardsWatchers() {
|
||||||
takeEvery(EntryActionTypes.BOARD_DELETE_HANDLE, ({ payload: { board } }) =>
|
takeEvery(EntryActionTypes.BOARD_DELETE_HANDLE, ({ payload: { board } }) =>
|
||||||
services.handleBoardDelete(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,
|
||||||
|
),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue