mirror of
https://github.com/plankanban/planka.git
synced 2025-08-09 07:25:24 +02:00
fix: Separated cardIds, filteredCardIds, IsFiltered selectors
This commit is contained in:
parent
fcb4e22f7f
commit
4f8f4327fd
6 changed files with 68 additions and 27 deletions
|
@ -16,7 +16,7 @@ import styles from './List.module.scss';
|
||||||
|
|
||||||
const List = React.memo(
|
const List = React.memo(
|
||||||
// eslint-disable-next-line prettier/prettier
|
// eslint-disable-next-line prettier/prettier
|
||||||
({ id, index, name, isPersisted, isCollapsed, isFiltered, cardIds, cardIdsFull, canEdit, onUpdate, onDelete, onCardCreate }) => {
|
({ id, index, name, isPersisted, isCollapsed, cardIds, isFiltered, filteredCardIds, canEdit, onUpdate, onDelete, onCardCreate }) => {
|
||||||
const [t] = useTranslation();
|
const [t] = useTranslation();
|
||||||
const [isAddCardOpened, setIsAddCardOpened] = useState(false);
|
const [isAddCardOpened, setIsAddCardOpened] = useState(false);
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ const List = React.memo(
|
||||||
if (isAddCardOpened) {
|
if (isAddCardOpened) {
|
||||||
listWrapper.current.scrollTop = listWrapper.current.scrollHeight;
|
listWrapper.current.scrollTop = listWrapper.current.scrollHeight;
|
||||||
}
|
}
|
||||||
}, [cardIds, isAddCardOpened]);
|
}, [filteredCardIds, isAddCardOpened]);
|
||||||
|
|
||||||
const cardsNode = (
|
const cardsNode = (
|
||||||
<Droppable
|
<Droppable
|
||||||
|
@ -78,7 +78,7 @@ const List = React.memo(
|
||||||
// eslint-disable-next-line react/jsx-props-no-spreading
|
// eslint-disable-next-line react/jsx-props-no-spreading
|
||||||
<div {...droppableProps} ref={innerRef}>
|
<div {...droppableProps} ref={innerRef}>
|
||||||
<div className={styles.cards}>
|
<div className={styles.cards}>
|
||||||
{cardIds.map((cardId, cardIndex) => (
|
{filteredCardIds.map((cardId, cardIndex) => (
|
||||||
<CardContainer key={cardId} id={cardId} index={cardIndex} />
|
<CardContainer key={cardId} id={cardId} index={cardIndex} />
|
||||||
))}
|
))}
|
||||||
{placeholder}
|
{placeholder}
|
||||||
|
@ -99,9 +99,9 @@ const List = React.memo(
|
||||||
return (
|
return (
|
||||||
[
|
[
|
||||||
isFiltered
|
isFiltered
|
||||||
? `${cardIds.length} ${t('common.of')} ${cardIdsFull.length} `
|
? `${filteredCardIds.length} ${t('common.of')} ${cardIds.length} `
|
||||||
: `${cardIdsFull.length} `,
|
: `${cardIds.length} `,
|
||||||
] + [cardIdsFull.length !== 1 ? t('common.cards') : t('common.card')]
|
] + [cardIds.length !== 1 ? t('common.cards') : t('common.card')]
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -210,7 +210,7 @@ const List = React.memo(
|
||||||
>
|
>
|
||||||
<PlusMathIcon className={styles.addCardButtonIcon} />
|
<PlusMathIcon className={styles.addCardButtonIcon} />
|
||||||
<span className={styles.addCardButtonText}>
|
<span className={styles.addCardButtonText}>
|
||||||
{cardIds.length > 0 ? t('action.addAnotherCard') : t('action.addCard')}
|
{filteredCardIds.length > 0 ? t('action.addAnotherCard') : t('action.addCard')}
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
|
@ -228,9 +228,9 @@ List.propTypes = {
|
||||||
name: PropTypes.string.isRequired,
|
name: PropTypes.string.isRequired,
|
||||||
isCollapsed: PropTypes.bool.isRequired,
|
isCollapsed: PropTypes.bool.isRequired,
|
||||||
isPersisted: PropTypes.bool.isRequired,
|
isPersisted: PropTypes.bool.isRequired,
|
||||||
isFiltered: PropTypes.bool.isRequired,
|
|
||||||
cardIds: PropTypes.array.isRequired, // eslint-disable-line react/forbid-prop-types
|
cardIds: PropTypes.array.isRequired, // eslint-disable-line react/forbid-prop-types
|
||||||
cardIdsFull: PropTypes.array.isRequired, // eslint-disable-line react/forbid-prop-types
|
isFiltered: PropTypes.bool.isRequired,
|
||||||
|
filteredCardIds: PropTypes.array.isRequired, // eslint-disable-line react/forbid-prop-types
|
||||||
canEdit: PropTypes.bool.isRequired,
|
canEdit: PropTypes.bool.isRequired,
|
||||||
onUpdate: PropTypes.func.isRequired,
|
onUpdate: PropTypes.func.isRequired,
|
||||||
onDelete: PropTypes.func.isRequired,
|
onDelete: PropTypes.func.isRequired,
|
||||||
|
|
|
@ -8,9 +8,7 @@ import BoardActions from '../components/BoardActions';
|
||||||
|
|
||||||
const mapStateToProps = (state) => {
|
const mapStateToProps = (state) => {
|
||||||
const listIds = selectors.selectListIdsForCurrentBoard(state);
|
const listIds = selectors.selectListIdsForCurrentBoard(state);
|
||||||
const listCardsCount = listIds.map(
|
const listCardsCount = listIds.map((list) => selectors.selectCardIdsByListId(state, list).length);
|
||||||
(list) => selectors.selectCardIdsByListId(state, list).cardIdsFull.length,
|
|
||||||
);
|
|
||||||
const cardCount = listCardsCount.reduce((sum, count) => sum + count, 0);
|
const cardCount = listCardsCount.reduce((sum, count) => sum + count, 0);
|
||||||
const allUsers = selectors.selectUsers(state);
|
const allUsers = selectors.selectUsers(state);
|
||||||
const isCurrentUserManager = selectors.selectIsCurrentUserManagerForCurrentProject(state);
|
const isCurrentUserManager = selectors.selectIsCurrentUserManagerForCurrentProject(state);
|
||||||
|
|
|
@ -9,10 +9,14 @@ import List from '../components/List';
|
||||||
const makeMapStateToProps = () => {
|
const makeMapStateToProps = () => {
|
||||||
const selectListById = selectors.makeSelectListById();
|
const selectListById = selectors.makeSelectListById();
|
||||||
const selectCardIdsByListId = selectors.makeSelectCardIdsByListId();
|
const selectCardIdsByListId = selectors.makeSelectCardIdsByListId();
|
||||||
|
const selectIsFilteredByListId = selectors.makeSelectIsFilteredByListId();
|
||||||
|
const selectFilteredCardIdsByListId = selectors.makeSelectFilteredCardIdsByListId();
|
||||||
|
|
||||||
return (state, { id, index }) => {
|
return (state, { id, index }) => {
|
||||||
const { name, isPersisted, isCollapsed } = selectListById(state, id);
|
const { name, isPersisted, isCollapsed } = selectListById(state, id);
|
||||||
const { cardIds, cardIdsFull, isFiltered } = selectCardIdsByListId(state, id);
|
const cardIds = selectCardIdsByListId(state, id);
|
||||||
|
const isFiltered = selectIsFilteredByListId(state, id);
|
||||||
|
const filteredCardIds = selectFilteredCardIdsByListId(state, id);
|
||||||
const currentUserMembership = selectors.selectCurrentUserMembershipForCurrentBoard(state);
|
const currentUserMembership = selectors.selectCurrentUserMembershipForCurrentBoard(state);
|
||||||
|
|
||||||
const isCurrentUserEditor =
|
const isCurrentUserEditor =
|
||||||
|
@ -24,9 +28,9 @@ const makeMapStateToProps = () => {
|
||||||
name,
|
name,
|
||||||
isCollapsed,
|
isCollapsed,
|
||||||
isPersisted,
|
isPersisted,
|
||||||
isFiltered,
|
|
||||||
cardIds,
|
cardIds,
|
||||||
cardIdsFull,
|
isFiltered,
|
||||||
|
filteredCardIds,
|
||||||
canEdit: isCurrentUserEditor,
|
canEdit: isCurrentUserEditor,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -85,18 +85,25 @@ export default class extends BaseModel {
|
||||||
return this.cards.orderBy('position');
|
return this.cards.orderBy('position');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getOrderedCardsModelArray() {
|
||||||
|
return this.getOrderedCardsQuerySet().toModelArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
getIsFiltered() {
|
||||||
|
const filterUserIds = this.board.filterUsers.toRefArray().map((user) => user.id);
|
||||||
|
const filterLabelIds = this.board.filterLabels.toRefArray().map((label) => label.id);
|
||||||
|
return filterUserIds.length > 0 || filterLabelIds.length > 0;
|
||||||
|
}
|
||||||
|
|
||||||
getFilteredOrderedCardsModelArray() {
|
getFilteredOrderedCardsModelArray() {
|
||||||
let cardModels = this.getOrderedCardsQuerySet().toModelArray();
|
let cardModels = this.getOrderedCardsQuerySet().toModelArray();
|
||||||
const cardModelsFull = cardModels;
|
|
||||||
|
|
||||||
const filterUserIds = this.board.filterUsers.toRefArray().map((user) => user.id);
|
const filterUserIds = this.board.filterUsers.toRefArray().map((user) => user.id);
|
||||||
const filterLabelIds = this.board.filterLabels.toRefArray().map((label) => label.id);
|
const filterLabelIds = this.board.filterLabels.toRefArray().map((label) => label.id);
|
||||||
let isFiltered = false;
|
|
||||||
|
|
||||||
if (filterUserIds.length > 0) {
|
if (filterUserIds.length > 0) {
|
||||||
cardModels = cardModels.filter((cardModel) => {
|
cardModels = cardModels.filter((cardModel) => {
|
||||||
const users = cardModel.users.toRefArray();
|
const users = cardModel.users.toRefArray();
|
||||||
isFiltered = true;
|
|
||||||
return users.some((user) => filterUserIds.includes(user.id));
|
return users.some((user) => filterUserIds.includes(user.id));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -104,12 +111,11 @@ export default class extends BaseModel {
|
||||||
if (filterLabelIds.length > 0) {
|
if (filterLabelIds.length > 0) {
|
||||||
cardModels = cardModels.filter((cardModel) => {
|
cardModels = cardModels.filter((cardModel) => {
|
||||||
const labels = cardModel.labels.toRefArray();
|
const labels = cardModel.labels.toRefArray();
|
||||||
isFiltered = true;
|
|
||||||
return labels.some((label) => filterLabelIds.includes(label.id));
|
return labels.some((label) => filterLabelIds.includes(label.id));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return { cardModels, cardModelsFull, isFiltered };
|
return cardModels;
|
||||||
}
|
}
|
||||||
|
|
||||||
deleteRelated() {
|
deleteRelated() {
|
||||||
|
|
|
@ -94,7 +94,7 @@ export const selectNextCardPosition = createSelector(
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line prettier/prettier
|
// eslint-disable-next-line prettier/prettier
|
||||||
return nextPosition(listModel.getFilteredOrderedCardsModelArray().cardModels, index, excludedId);
|
return nextPosition(listModel.getFilteredOrderedCardsModelArray(), index, excludedId);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -34,20 +34,53 @@ export const makeSelectCardIdsByListId = () =>
|
||||||
return listModel;
|
return listModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
const cardsModelArray = listModel.getFilteredOrderedCardsModelArray();
|
return listModel.getOrderedCardsModelArray().map((cardModel) => cardModel.id);
|
||||||
return {
|
|
||||||
cardIds: cardsModelArray.cardModels.map((cardModel) => cardModel.id),
|
|
||||||
cardIdsFull: cardsModelArray.cardModelsFull.map((cardModel) => cardModel.id),
|
|
||||||
isFiltered: cardsModelArray.isFiltered,
|
|
||||||
};
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
export const selectCardIdsByListId = makeSelectCardIdsByListId();
|
export const selectCardIdsByListId = makeSelectCardIdsByListId();
|
||||||
|
|
||||||
|
export const makeSelectIsFilteredByListId = () =>
|
||||||
|
createSelector(
|
||||||
|
orm,
|
||||||
|
(_, id) => id,
|
||||||
|
({ List }, id) => {
|
||||||
|
const listModel = List.withId(id);
|
||||||
|
|
||||||
|
if (!listModel) {
|
||||||
|
return listModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
return listModel.getIsFiltered();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
export const selectIsFilteredByListId = makeSelectIsFilteredByListId();
|
||||||
|
|
||||||
|
export const makeSelectFilteredCardIdsByListId = () =>
|
||||||
|
createSelector(
|
||||||
|
orm,
|
||||||
|
(_, id) => id,
|
||||||
|
({ List }, id) => {
|
||||||
|
const listModel = List.withId(id);
|
||||||
|
|
||||||
|
if (!listModel) {
|
||||||
|
return listModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
return listModel.getFilteredOrderedCardsModelArray().map((cardModel) => cardModel.id);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
export const selectFilteredCardIdsByListId = makeSelectFilteredCardIdsByListId();
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
makeSelectListById,
|
makeSelectListById,
|
||||||
selectListById,
|
selectListById,
|
||||||
makeSelectCardIdsByListId,
|
makeSelectCardIdsByListId,
|
||||||
selectCardIdsByListId,
|
selectCardIdsByListId,
|
||||||
|
makeSelectIsFilteredByListId,
|
||||||
|
selectIsFilteredByListId,
|
||||||
|
makeSelectFilteredCardIdsByListId,
|
||||||
|
selectFilteredCardIdsByListId,
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue