diff --git a/client/package-lock.json b/client/package-lock.json
index ba590d32..19dbf347 100644
--- a/client/package-lock.json
+++ b/client/package-lock.json
@@ -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",
diff --git a/client/package.json b/client/package.json
index a36321fb..36f0349f 100644
--- a/client/package.json
+++ b/client/package.json
@@ -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",
diff --git a/client/src/components/cards/CardModal/CardModal.jsx b/client/src/components/cards/CardModal/CardModal.jsx
index 3d86c94c..4098e82d 100755
--- a/client/src/components/cards/CardModal/CardModal.jsx
+++ b/client/src/components/cards/CardModal/CardModal.jsx
@@ -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 && (
+
+ )}
{canEdit ? (
diff --git a/client/src/components/cards/CardModal/CardModal.module.scss b/client/src/components/cards/CardModal/CardModal.module.scss
index 88988448..789dc5b0 100644
--- a/client/src/components/cards/CardModal/CardModal.module.scss
+++ b/client/src/components/cards/CardModal/CardModal.module.scss
@@ -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;
+ }
}
}
diff --git a/client/src/reducers/core.js b/client/src/reducers/core.js
index ff71188c..aab57e4b 100755
--- a/client/src/reducers/core.js
+++ b/client/src/reducers/core.js
@@ -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;
}
diff --git a/client/src/selectors/core.js b/client/src/selectors/core.js
index d7a37c1e..39189a25 100644
--- a/client/src/selectors/core.js
+++ b/client/src/selectors/core.js
@@ -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,