1
0
Fork 0
mirror of https://github.com/plankanban/planka.git synced 2025-07-18 12:49:43 +02:00
This commit is contained in:
Symon Baikov 2025-07-18 04:03:48 +02:00 committed by GitHub
commit 05458d629a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 84 additions and 0 deletions

View file

@ -147,6 +147,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}>
@ -161,6 +169,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 && (
<button type="button" className={styles.filterButton} onClick={handleCurrentUserSelect}>
<span className={styles.filterLabel}>

View file

@ -216,6 +216,9 @@ export default {
LABEL_TO_BOARD_FILTER_ADD: 'LABEL_TO_BOARD_FILTER_ADD',
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 */
LIST_CREATE: 'LIST_CREATE',

View file

@ -285,4 +285,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`,
};

View file

@ -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,
};

View file

@ -222,6 +222,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',

View file

@ -61,6 +61,9 @@ export default class extends BaseModel {
}),
filterUsers: many('User', 'filterBoards'),
filterLabels: many('Label', 'filterBoards'),
filterNoMember: attr({
getDefault: () => false,
}),
};
static reducer({ type, payload }, Board) {
@ -268,6 +271,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:
}
}
@ -387,6 +401,11 @@ export default class extends BaseModel {
});
}
if (this.filterNoMember) {
cardModels = cardModels.filter((cardModel) => cardModel.users.toRefArray().length === 0);
return cardModels;
}
return cardModels;
}

View file

@ -379,6 +379,11 @@ export default class extends BaseModel {
});
}
if (this.board.filterNoMember) {
cardModels = cardModels.filter((cardModel) => cardModel.users.toRefArray().length === 0);
return cardModels;
}
return cardModels;
}

View file

@ -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 {
createBoard,
createBoardInCurrentProject,
@ -261,4 +277,6 @@ export default {
searchInCurrentBoard,
deleteBoard,
handleBoardDelete,
setNoMemberToFilterInCurrentBoard,
removeNoMemberFromFilterInCurrentBoard,
};

View file

@ -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,
),
]);
}