mirror of
https://github.com/plankanban/planka.git
synced 2025-08-06 05:55:27 +02:00
feat: Track navigation path when switching between cards
This commit is contained in:
parent
a37a6b45b1
commit
0049ba2145
6 changed files with 69 additions and 5 deletions
8
client/package-lock.json
generated
8
client/package-lock.json
generated
|
@ -49,7 +49,7 @@
|
||||||
"javascript-time-ago": "^2.5.11",
|
"javascript-time-ago": "^2.5.11",
|
||||||
"js-cookie": "^3.0.5",
|
"js-cookie": "^3.0.5",
|
||||||
"jwt-decode": "^4.0.0",
|
"jwt-decode": "^4.0.0",
|
||||||
"linkify-react": "^4.3.1",
|
"linkify-react": "^4.3.2",
|
||||||
"linkifyjs": "^4.3.2",
|
"linkifyjs": "^4.3.2",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"lowlight": "^3.3.0",
|
"lowlight": "^3.3.0",
|
||||||
|
@ -11079,9 +11079,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/linkify-react": {
|
"node_modules/linkify-react": {
|
||||||
"version": "4.3.1",
|
"version": "4.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/linkify-react/-/linkify-react-4.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/linkify-react/-/linkify-react-4.3.2.tgz",
|
||||||
"integrity": "sha512-w8ahBdCwF9C/doS4V3nE93QF1oyORmosvi8UEUbpHYws077eGzhkxUzJQcE2/SU5Q2K7SD80M4ybwwZGHErx5Q==",
|
"integrity": "sha512-mi744h1hf+WDsr+paJgSBBgYNLMWNSHyM9V9LVUo03RidNGdw1VpI7Twnt+K3pEh3nIzB4xiiAgZxpd61ItKpQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"linkifyjs": "^4.0.0",
|
"linkifyjs": "^4.0.0",
|
||||||
|
|
|
@ -120,7 +120,7 @@
|
||||||
"javascript-time-ago": "^2.5.11",
|
"javascript-time-ago": "^2.5.11",
|
||||||
"js-cookie": "^3.0.5",
|
"js-cookie": "^3.0.5",
|
||||||
"jwt-decode": "^4.0.0",
|
"jwt-decode": "^4.0.0",
|
||||||
"linkify-react": "^4.3.1",
|
"linkify-react": "^4.3.2",
|
||||||
"linkifyjs": "^4.3.2",
|
"linkifyjs": "^4.3.2",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"lowlight": "^3.3.0",
|
"lowlight": "^3.3.0",
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
import React, { useCallback, useEffect, useMemo } from 'react';
|
import React, { useCallback, useEffect, useMemo } from 'react';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { useDispatch, useSelector } from 'react-redux';
|
import { useDispatch, useSelector } from 'react-redux';
|
||||||
|
import { Icon } from 'semantic-ui-react';
|
||||||
import { push } from '../../../lib/redux-router';
|
import { push } from '../../../lib/redux-router';
|
||||||
|
|
||||||
import selectors from '../../../selectors';
|
import selectors from '../../../selectors';
|
||||||
|
@ -30,6 +31,7 @@ const CardModal = React.memo(() => {
|
||||||
const selectListById = useMemo(() => selectors.makeSelectListById(), []);
|
const selectListById = useMemo(() => selectors.makeSelectListById(), []);
|
||||||
|
|
||||||
const card = useSelector(selectors.selectCurrentCard);
|
const card = useSelector(selectors.selectCurrentCard);
|
||||||
|
const prevCardId = useSelector(selectors.selectPrevCardId);
|
||||||
|
|
||||||
const canEdit = useSelector((state) => {
|
const canEdit = useSelector((state) => {
|
||||||
const list = selectListById(state, card.listId);
|
const list = selectListById(state, card.listId);
|
||||||
|
@ -48,6 +50,10 @@ const CardModal = React.memo(() => {
|
||||||
dispatch(push(Paths.BOARDS.replace(':id', card.boardId)));
|
dispatch(push(Paths.BOARDS.replace(':id', card.boardId)));
|
||||||
}, [card.boardId, dispatch]);
|
}, [card.boardId, dispatch]);
|
||||||
|
|
||||||
|
const handlePrevClick = useCallback(() => {
|
||||||
|
dispatch(push(Paths.CARDS.replace(':id', prevCardId)));
|
||||||
|
}, [prevCardId, dispatch]);
|
||||||
|
|
||||||
const [ClosableModal, isClosableActiveRef] = useClosableModal();
|
const [ClosableModal, isClosableActiveRef] = useClosableModal();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -95,6 +101,11 @@ const CardModal = React.memo(() => {
|
||||||
className={classNames(styles.wrapper, card.type === CardTypes.STORY && styles.wrapperStory)}
|
className={classNames(styles.wrapper, card.type === CardTypes.STORY && styles.wrapperStory)}
|
||||||
onClose={handleClose}
|
onClose={handleClose}
|
||||||
>
|
>
|
||||||
|
{prevCardId && (
|
||||||
|
<button type="button" className={styles.prevButton} onClick={handlePrevClick}>
|
||||||
|
<Icon fitted name="arrow left" size="large" className={styles.prevButtonIcon} />
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
{canEdit ? (
|
{canEdit ? (
|
||||||
<AddAttachmentZone>
|
<AddAttachmentZone>
|
||||||
<Content onClose={handleClose} />
|
<Content onClose={handleClose} />
|
||||||
|
|
|
@ -9,6 +9,34 @@
|
||||||
width: 95%;
|
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 {
|
.wrapper {
|
||||||
margin: 2rem auto;
|
margin: 2rem auto;
|
||||||
width: 880px;
|
width: 880px;
|
||||||
|
@ -24,5 +52,13 @@
|
||||||
@media (width < 1026px) {
|
@media (width < 1026px) {
|
||||||
@include smallScreen;
|
@include smallScreen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.prevButton {
|
||||||
|
padding: 20px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.prevButtonIcon {
|
||||||
|
top: 7px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,9 @@ const initialState = {
|
||||||
isEditModeEnabled: false,
|
isEditModeEnabled: false,
|
||||||
modal: null,
|
modal: null,
|
||||||
boardId: null,
|
boardId: null,
|
||||||
|
cardId: null,
|
||||||
recentCardId: null,
|
recentCardId: null,
|
||||||
|
prevCardIds: [],
|
||||||
homeView: HomeViews.GROUPED_PROJECTS,
|
homeView: HomeViews.GROUPED_PROJECTS,
|
||||||
projectsSearch: '',
|
projectsSearch: '',
|
||||||
projectsOrder: ProjectOrders.BY_DEFAULT,
|
projectsOrder: ProjectOrders.BY_DEFAULT,
|
||||||
|
@ -37,6 +39,7 @@ export default (state = initialState, { type, payload }) => {
|
||||||
...state,
|
...state,
|
||||||
isContentFetching: false,
|
isContentFetching: false,
|
||||||
boardId: payload.currentBoardId,
|
boardId: payload.currentBoardId,
|
||||||
|
cardId: payload.currentCardId,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (payload.currentCardId) {
|
if (payload.currentCardId) {
|
||||||
|
@ -45,6 +48,17 @@ export default (state = initialState, { type, payload }) => {
|
||||||
nextState.recentCardId = null;
|
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) {
|
if (payload.isEditModeEnabled !== undefined) {
|
||||||
nextState.isEditModeEnabled = payload.isEditModeEnabled;
|
nextState.isEditModeEnabled = payload.isEditModeEnabled;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,8 @@ export const selectIsEditModeEnabled = ({ core: { isEditModeEnabled } }) => isEd
|
||||||
|
|
||||||
export const selectRecentCardId = ({ core: { recentCardId } }) => recentCardId;
|
export const selectRecentCardId = ({ core: { recentCardId } }) => recentCardId;
|
||||||
|
|
||||||
|
export const selectPrevCardId = ({ core: { prevCardIds } }) => prevCardIds.at(-1);
|
||||||
|
|
||||||
export const selectHomeView = ({ core: { homeView } }) => homeView;
|
export const selectHomeView = ({ core: { homeView } }) => homeView;
|
||||||
|
|
||||||
export const selectProjectsSearch = ({ core: { projectsSearch } }) => projectsSearch;
|
export const selectProjectsSearch = ({ core: { projectsSearch } }) => projectsSearch;
|
||||||
|
@ -28,6 +30,7 @@ export default {
|
||||||
selectIsFavoritesEnabled,
|
selectIsFavoritesEnabled,
|
||||||
selectIsEditModeEnabled,
|
selectIsEditModeEnabled,
|
||||||
selectRecentCardId,
|
selectRecentCardId,
|
||||||
|
selectPrevCardId,
|
||||||
selectHomeView,
|
selectHomeView,
|
||||||
selectProjectsSearch,
|
selectProjectsSearch,
|
||||||
selectProjectsOrder,
|
selectProjectsOrder,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue