A board level switch, off by default. With it on, each list puts its card count on the add-card button. Useful to a board that is being kept to a size and noise to one that is not, which is why it is a choice rather than always on. The count is every card in the list, not the ones a filter leaves visible. Those answer different questions: how full is this list, versus how many match what I am looking at right now. The first is the one a counter is for, and it is also what the same switch counts in Pro, so a board keeps its meaning across an upgrade. The column matches Pro's name, type and default, so the setting survives that upgrade rather than being dropped on the way.
203 lines
4.4 KiB
JavaScript
203 lines
4.4 KiB
JavaScript
/*!
|
|
* Copyright (c) 2024 PLANKA Software GmbH
|
|
* Licensed under the Fair Use License: https://github.com/plankanban/planka/blob/master/LICENSE.md
|
|
*/
|
|
|
|
import { createSelector } from 'redux-orm';
|
|
|
|
import orm from '../orm';
|
|
import { selectPath } from './router';
|
|
import { selectCurrentUserId } from './users';
|
|
import { isLocalId } from '../utils/local-id';
|
|
import { BoardContexts, ListTypes } from '../constants/Enums';
|
|
|
|
export const makeSelectListById = () =>
|
|
createSelector(
|
|
orm,
|
|
(_, id) => id,
|
|
({ List }, id) => {
|
|
const listModel = List.withId(id);
|
|
|
|
if (!listModel) {
|
|
return listModel;
|
|
}
|
|
|
|
return {
|
|
...listModel.ref,
|
|
isPersisted: !isLocalId(id),
|
|
};
|
|
},
|
|
);
|
|
|
|
export const selectListById = makeSelectListById();
|
|
|
|
export const makeSelectCardIdsByListId = () =>
|
|
createSelector(
|
|
orm,
|
|
(_, id) => id,
|
|
({ List }, id) => {
|
|
const listModel = List.withId(id);
|
|
|
|
if (!listModel) {
|
|
return listModel;
|
|
}
|
|
|
|
return listModel.getCardsModelArray().map((cardModel) => cardModel.id);
|
|
},
|
|
);
|
|
|
|
export const selectCardIdsByListId = makeSelectCardIdsByListId();
|
|
|
|
export const makeSelectFilteredCardIdsByListId = () =>
|
|
createSelector(
|
|
orm,
|
|
(_, id) => id,
|
|
({ List }, id) => {
|
|
const listModel = List.withId(id);
|
|
|
|
if (!listModel) {
|
|
return listModel;
|
|
}
|
|
|
|
return listModel.getFilteredCardsModelArray().map((cardModel) => cardModel.id);
|
|
},
|
|
);
|
|
|
|
export const selectFilteredCardIdsByListId = makeSelectFilteredCardIdsByListId();
|
|
|
|
// How many cards the list holds.
|
|
//
|
|
// Unfiltered on purpose: a filter hides cards, it does not remove them, and a
|
|
// count that fell as the filter narrowed would say the list had emptied.
|
|
export const makeSelectCardCountByListId = () =>
|
|
createSelector(
|
|
orm,
|
|
(_, id) => id,
|
|
({ List }, id) => {
|
|
const listModel = List.withId(id);
|
|
|
|
if (!listModel) {
|
|
return null;
|
|
}
|
|
|
|
return listModel.getCardsModelArray().length;
|
|
},
|
|
);
|
|
|
|
export const selectCardCountByListId = makeSelectCardCountByListId();
|
|
|
|
export const selectIsListWithIdAvailableForCurrentUser = createSelector(
|
|
orm,
|
|
(_, id) => id,
|
|
(state) => selectCurrentUserId(state),
|
|
({ List, User }, id, currentUserId) => {
|
|
const listModel = List.withId(id);
|
|
|
|
if (!listModel) {
|
|
return false;
|
|
}
|
|
|
|
const currentUserModel = User.withId(currentUserId);
|
|
return listModel.isAvailableForUser(currentUserModel);
|
|
},
|
|
);
|
|
|
|
export const selectCurrentListId = createSelector(
|
|
orm,
|
|
(state) => selectPath(state).boardId,
|
|
({ Board }, id) => {
|
|
if (!id) {
|
|
return id;
|
|
}
|
|
|
|
const boardModel = Board.withId(id);
|
|
|
|
if (!boardModel) {
|
|
return boardModel;
|
|
}
|
|
|
|
if (boardModel.context === BoardContexts.BOARD) {
|
|
return null;
|
|
}
|
|
|
|
const listModel = boardModel.lists
|
|
.filter({
|
|
type: boardModel.context || ListTypes.ACTIVE, // TODO: hack?
|
|
})
|
|
.first();
|
|
|
|
return listModel && listModel.id;
|
|
},
|
|
);
|
|
|
|
export const selectCurrentList = createSelector(
|
|
orm,
|
|
(state) => selectCurrentListId(state),
|
|
({ List }, id) => {
|
|
if (!id) {
|
|
return id;
|
|
}
|
|
|
|
const listModel = List.withId(id);
|
|
|
|
if (!listModel) {
|
|
return listModel;
|
|
}
|
|
|
|
return listModel.ref;
|
|
},
|
|
);
|
|
|
|
export const selectFirstKanbanListId = createSelector(
|
|
orm,
|
|
(state) => selectPath(state).boardId,
|
|
({ Board }, id) => {
|
|
if (!id) {
|
|
return id;
|
|
}
|
|
|
|
const boardModel = Board.withId(id);
|
|
|
|
if (!boardModel) {
|
|
return boardModel;
|
|
}
|
|
|
|
const listModel = boardModel.getKanbanListsQuerySet().first();
|
|
return listModel && listModel.id;
|
|
},
|
|
);
|
|
|
|
export const selectFilteredCardIdsForCurrentList = createSelector(
|
|
orm,
|
|
(state) => selectCurrentListId(state),
|
|
({ List }, id) => {
|
|
if (!id) {
|
|
return id;
|
|
}
|
|
|
|
const listModel = List.withId(id);
|
|
|
|
if (!listModel) {
|
|
return listModel;
|
|
}
|
|
|
|
return listModel.getFilteredCardsModelArray().map((cardModel) => cardModel.id);
|
|
},
|
|
);
|
|
|
|
export default {
|
|
makeSelectListById,
|
|
selectListById,
|
|
makeSelectCardIdsByListId,
|
|
selectCardIdsByListId,
|
|
makeSelectFilteredCardIdsByListId,
|
|
selectFilteredCardIdsByListId,
|
|
makeSelectCardCountByListId,
|
|
selectCardCountByListId,
|
|
selectIsListWithIdAvailableForCurrentUser,
|
|
selectCurrentListId,
|
|
selectCurrentList,
|
|
selectFirstKanbanListId,
|
|
selectFilteredCardIdsForCurrentList,
|
|
};
|