1
0
Fork 0
mirror of https://github.com/plankanban/planka.git synced 2025-08-05 05:25:29 +02:00

feat: Track navigation path when switching between cards

This commit is contained in:
Maksim Eltyshev 2025-07-31 16:59:16 +02:00
parent a37a6b45b1
commit 0049ba2145
6 changed files with 69 additions and 5 deletions

View file

@ -49,7 +49,7 @@
"javascript-time-ago": "^2.5.11",
"js-cookie": "^3.0.5",
"jwt-decode": "^4.0.0",
"linkify-react": "^4.3.1",
"linkify-react": "^4.3.2",
"linkifyjs": "^4.3.2",
"lodash": "^4.17.21",
"lowlight": "^3.3.0",
@ -11079,9 +11079,9 @@
}
},
"node_modules/linkify-react": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/linkify-react/-/linkify-react-4.3.1.tgz",
"integrity": "sha512-w8ahBdCwF9C/doS4V3nE93QF1oyORmosvi8UEUbpHYws077eGzhkxUzJQcE2/SU5Q2K7SD80M4ybwwZGHErx5Q==",
"version": "4.3.2",
"resolved": "https://registry.npmjs.org/linkify-react/-/linkify-react-4.3.2.tgz",
"integrity": "sha512-mi744h1hf+WDsr+paJgSBBgYNLMWNSHyM9V9LVUo03RidNGdw1VpI7Twnt+K3pEh3nIzB4xiiAgZxpd61ItKpQ==",
"license": "MIT",
"peerDependencies": {
"linkifyjs": "^4.0.0",

View file

@ -120,7 +120,7 @@
"javascript-time-ago": "^2.5.11",
"js-cookie": "^3.0.5",
"jwt-decode": "^4.0.0",
"linkify-react": "^4.3.1",
"linkify-react": "^4.3.2",
"linkifyjs": "^4.3.2",
"lodash": "^4.17.21",
"lowlight": "^3.3.0",

View file

@ -6,6 +6,7 @@
import React, { useCallback, useEffect, useMemo } from 'react';
import classNames from 'classnames';
import { useDispatch, useSelector } from 'react-redux';
import { Icon } from 'semantic-ui-react';
import { push } from '../../../lib/redux-router';
import selectors from '../../../selectors';
@ -30,6 +31,7 @@ const CardModal = React.memo(() => {
const selectListById = useMemo(() => selectors.makeSelectListById(), []);
const card = useSelector(selectors.selectCurrentCard);
const prevCardId = useSelector(selectors.selectPrevCardId);
const canEdit = useSelector((state) => {
const list = selectListById(state, card.listId);
@ -48,6 +50,10 @@ const CardModal = React.memo(() => {
dispatch(push(Paths.BOARDS.replace(':id', card.boardId)));
}, [card.boardId, dispatch]);
const handlePrevClick = useCallback(() => {
dispatch(push(Paths.CARDS.replace(':id', prevCardId)));
}, [prevCardId, dispatch]);
const [ClosableModal, isClosableActiveRef] = useClosableModal();
useEffect(() => {
@ -95,6 +101,11 @@ const CardModal = React.memo(() => {
className={classNames(styles.wrapper, card.type === CardTypes.STORY && styles.wrapperStory)}
onClose={handleClose}
>
{prevCardId && (
<button type="button" className={styles.prevButton} onClick={handlePrevClick}>
<Icon fitted name="arrow left" size="large" className={styles.prevButtonIcon} />
</button>
)}
{canEdit ? (
<AddAttachmentZone>
<Content onClose={handleClose} />

View file

@ -9,6 +9,34 @@
width: 95%;
}
.prevButton {
background: rgba(255, 255, 255, 0.036);
border: none;
border-radius: 4px;
cursor: pointer;
display: flex;
height: 100%;
justify-content: center;
left: -120px;
padding: 18px 0;
position: absolute;
width: 100px;
&:hover {
background: rgba(255, 255, 255, 0.072);
.prevkButtonIcon {
color: rgba(255, 255, 255, 0.72);
}
}
}
.prevButtonIcon {
color: rgba(255, 255, 255, 0.36);
position: sticky;
top: 5px;
}
.wrapper {
margin: 2rem auto;
width: 880px;
@ -24,5 +52,13 @@
@media (width < 1026px) {
@include smallScreen;
}
.prevButton {
padding: 20px 0;
}
.prevButtonIcon {
top: 7px;
}
}
}

View file

@ -16,7 +16,9 @@ const initialState = {
isEditModeEnabled: false,
modal: null,
boardId: null,
cardId: null,
recentCardId: null,
prevCardIds: [],
homeView: HomeViews.GROUPED_PROJECTS,
projectsSearch: '',
projectsOrder: ProjectOrders.BY_DEFAULT,
@ -37,6 +39,7 @@ export default (state = initialState, { type, payload }) => {
...state,
isContentFetching: false,
boardId: payload.currentBoardId,
cardId: payload.currentCardId,
};
if (payload.currentCardId) {
@ -45,6 +48,17 @@ export default (state = initialState, { type, payload }) => {
nextState.recentCardId = null;
}
if (payload.currentCardId) {
if (state.cardId) {
nextState.prevCardIds =
payload.currentCardId === nextState.prevCardIds.at(-1)
? [...nextState.prevCardIds.slice(0, -1)]
: [...nextState.prevCardIds, state.cardId];
}
} else if (nextState.prevCardIds.length > 0) {
nextState.prevCardIds = [];
}
if (payload.isEditModeEnabled !== undefined) {
nextState.isEditModeEnabled = payload.isEditModeEnabled;
}

View file

@ -13,6 +13,8 @@ export const selectIsEditModeEnabled = ({ core: { isEditModeEnabled } }) => isEd
export const selectRecentCardId = ({ core: { recentCardId } }) => recentCardId;
export const selectPrevCardId = ({ core: { prevCardIds } }) => prevCardIds.at(-1);
export const selectHomeView = ({ core: { homeView } }) => homeView;
export const selectProjectsSearch = ({ core: { projectsSearch } }) => projectsSearch;
@ -28,6 +30,7 @@ export default {
selectIsFavoritesEnabled,
selectIsEditModeEnabled,
selectRecentCardId,
selectPrevCardId,
selectHomeView,
selectProjectsSearch,
selectProjectsOrder,