Repository: inovex/scrumlr.io
Pull request #2160 (2022-09-13 13:02:46)

Implement button to return to focused note


Patch:
diff --git a/public/locales/de/translation.json b/public/locales/de/translation.json
index 3b2ee569..e3bbb1f3 100644
--- a/public/locales/de/translation.json
+++ b/public/locales/de/translation.json
@@ -1,4 +1,7 @@
 {
+  "InfoBar": {
+    "ReturnToFocusedNote": "Zurück zur Fokuskarte"
+  },
   "NewBoard": {
     "boardName": "Sitzungsname",
     "createNewBoard": "Erstelle eine Sitzung",
diff --git a/public/locales/en/translation.json b/public/locales/en/translation.json
index 5ec279bd..378d31ec 100644
--- a/public/locales/en/translation.json
+++ b/public/locales/en/translation.json
@@ -1,4 +1,7 @@
 {
+  "InfoBar": {
+    "ReturnToFocusedNote": "Return to focused note"
+  },
   "NewBoard": {
     "boardName": "Board name",
     "createNewBoard": "Create new Board",
diff --git a/src/components/Infobar/Infobar.scss b/src/components/Infobar/Infobar.scss
index c7056640..0f24c182 100644
--- a/src/components/Infobar/Infobar.scss
+++ b/src/components/Infobar/Infobar.scss
@@ -8,7 +8,6 @@
   top: $header__height;
   left: 50%;
   transform: translateX(-50%);
-  width: 270px;
   justify-content: center;
   z-index: $infobar-z-index;
 }
@@ -21,3 +20,12 @@
   display: grid;
   grid-template-columns: 1fr auto 1fr;
 }
+
+.info-bar__return-to-focused-note-button > svg {
+  background-color: #333948;
+  color: $color-white;
+}
+[theme="dark"] .info-bar__return-to-focused-note-button > svg {
+  background-color: $color-white;
+  color: #333948;
+}
diff --git a/src/components/Infobar/Infobar.tsx b/src/components/Infobar/Infobar.tsx
index f204825c..976a81e3 100644
--- a/src/components/Infobar/Infobar.tsx
+++ b/src/components/Infobar/Infobar.tsx
@@ -1,17 +1,24 @@
+import {useNavigate} from "react-router";
+import {useTranslation} from "react-i18next";
 import {Timer} from "components/Timer";
 import {VoteDisplay} from "components/Votes/VoteDisplay";
 import ReactDOM from "react-dom";
-import "./Infobar.scss";
 import _ from "underscore";
 import {useAppSelector} from "store";
+import {TooltipButton} from "components/TooltipButton/TooltipButton";
+import {ReactComponent as ShareIcon} from "assets/icon-share.svg";
+import "./Infobar.scss";
 
 export const InfoBar = () => {
+  const navigate = useNavigate();
+  const {t} = useTranslation();
   const state = useAppSelector(
     (applicationState) => ({
       endTime: applicationState.board.data?.timerEnd,
       activeVoting: Boolean(applicationState.votings.open),
       possibleVotes: applicationState.votings.open?.voteLimit,
       usedVotes: applicationState.votes.filter((v) => v.voting === applicationState.votings.open?.id).length,
+      sharedNote: applicationState.board.data?.sharedNote,
     }),
     _.isEqual
   );
@@ -20,6 +27,15 @@ export const InfoBar = () => {
     <aside className="info-bar">
       {state.endTime && <Timer endTime={state.endTime} />}
       {state.activeVoting && <VoteDisplay usedVotes={state.usedVotes} possibleVotes={state.possibleVotes!} />}
+      {state.sharedNote && (
+        <TooltipButton
+          className="info-bar__return-to-focused-note-button"
+          icon={ShareIcon}
+          direction="right"
+          label={t("InfoBar.ReturnToFocusedNote")}
+          onClick={() => navigate(`stack/${state.sharedNote}`)}
+        />
+      )}
     </aside>,
     document.getElementById("root")!
   );


Test patch:
diff --git a/src/components/Infobar/__tests__/Infobar.test.tsx b/src/components/Infobar/__tests__/Infobar.test.tsx
index 7fcb874a..7e3bdabb 100644
--- a/src/components/Infobar/__tests__/Infobar.test.tsx
+++ b/src/components/Infobar/__tests__/Infobar.test.tsx
@@ -5,14 +5,18 @@ import {ApplicationState} from "types";
 import getTestStore from "utils/test/getTestStore";
 import {I18nextProvider} from "react-i18next";
 import i18nTest from "i18nTest";
+import {Router} from "react-router";
+import {createBrowserHistory} from "history";
 
 const renderInfoBar = (overwrite?: Partial<ApplicationState>) => {
   return render(
-    <I18nextProvider i18n={i18nTest}>
-      <Provider store={getTestStore(overwrite)}>
-        <InfoBar />
-      </Provider>
-    </I18nextProvider>,
+    <Router navigator={createBrowserHistory()} location={location}>
+      <I18nextProvider i18n={i18nTest}>
+        <Provider store={getTestStore(overwrite)}>
+          <InfoBar />
+        </Provider>
+      </I18nextProvider>
+    </Router>,
     {container: document.getElementById("root")!}
   );
 };
@@ -24,52 +28,44 @@ describe("InfoBar", () => {
     global.document.body.appendChild(root);
   });
 
-  describe("should render correctly", () => {
-    test("with disabled voting and timer", () => {
-      const {container} = renderInfoBar({votings: {open: undefined, past: []}});
-      expect(container).toMatchSnapshot();
-    });
-
-    test("with disabled voting and active timer", () => {
-      const {container} = renderInfoBar({
-        votings: {open: undefined, past: []},
-        board: {
-          status: "ready",
-          data: {
-            id: "test-board-id",
-            name: "test-board-name",
-            accessPolicy: "PUBLIC",
-            showAuthors: true,
-            showNotesOfOtherUsers: true,
-            allowStacking: true,
-            timerEnd: new Date(123456789),
-          },
+  test("should have timer component during active timer", () => {
+    const {container} = renderInfoBar({
+      board: {
+        status: "ready",
+        data: {
+          id: "test-board-id",
+          name: "test-board-name",
+          accessPolicy: "PUBLIC",
+          showAuthors: true,
+          showNotesOfOtherUsers: true,
+          allowStacking: true,
+          timerEnd: new Date(123456789),
         },
-      });
-      expect(container).toMatchSnapshot();
+      },
     });
+    expect(container.getElementsByClassName("timer").length).toBe(1);
+  });
 
-    test("with active voting and disabled timer", () => {
-      const {container} = renderInfoBar();
-      expect(container).toMatchSnapshot();
-    });
+  test("should have vote display component during active voting", () => {
+    const {container} = renderInfoBar();
+    expect(container.getElementsByClassName("vote-display").length).toBe(1);
+  });
 
-    test("with active voting and timer", () => {
-      const {container} = renderInfoBar({
-        board: {
-          status: "ready",
-          data: {
-            id: "test-board-id",
-            name: "test-board-name",
-            accessPolicy: "PUBLIC",
-            showAuthors: true,
-            showNotesOfOtherUsers: true,
-            allowStacking: true,
-            timerEnd: new Date(123456789),
-          },
+  test("should have return to focused not button during active sharing", () => {
+    const {container} = renderInfoBar({
+      board: {
+        status: "ready",
+        data: {
+          id: "test-board-id",
+          name: "test-board-name",
+          accessPolicy: "PUBLIC",
+          showAuthors: true,
+          showNotesOfOtherUsers: true,
+          allowStacking: true,
+          sharedNote: "test",
         },
-      });
-      expect(container).toMatchSnapshot();
+      },
     });
+    expect(container.getElementsByClassName("info-bar__return-to-focused-note-button").length).toBe(1);
   });
 });
diff --git a/src/components/Infobar/__tests__/__snapshots__/Infobar.test.tsx.snap b/src/components/Infobar/__tests__/__snapshots__/Infobar.test.tsx.snap
deleted file mode 100644
index 1c68d4cc..00000000
--- a/src/components/Infobar/__tests__/__snapshots__/Infobar.test.tsx.snap
+++ /dev/null
@@ -1,100 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`InfoBar should render correctly with active voting and disabled timer 1`] = `
-<div
-  id="root"
->
-  <aside
-    class="info-bar"
-  >
-    <div
-      class="vote-display"
-    >
-      <span
-        title="4 of 5 votes remaining"
-      >
-        1
-         / 
-        5
-      </span>
-    </div>
-  </aside>
-</div>
-`;
-
-exports[`InfoBar should render correctly with active voting and timer 1`] = `
-<div
-  id="root"
->
-  <aside
-    class="info-bar"
-  >
-    <div
-      class="timer timer--expired"
-      id="timer"
-    >
-      <span>
-        00
-        :
-        00
-      </span>
-      <button
-        title="Stop timer"
-      >
-        <svg>
-          icon-close.svg
-        </svg>
-      </button>
-    </div>
-    <div
-      class="vote-display"
-    >
-      <span
-        title="4 of 5 votes remaining"
-      >
-        1
-         / 
-        5
-      </span>
-    </div>
-  </aside>
-</div>
-`;
-
-exports[`InfoBar should render correctly with disabled voting and active timer 1`] = `
-<div
-  id="root"
->
-  <aside
-    class="info-bar"
-  >
-    <div
-      class="timer timer--expired"
-      id="timer"
-    >
-      <span>
-        00
-        :
-        00
-      </span>
-      <button
-        title="Stop timer"
-      >
-        <svg>
-          icon-close.svg
-        </svg>
-      </button>
-    </div>
-  </aside>
-</div>
-`;
-
-exports[`InfoBar should render correctly with disabled voting and timer 1`] = `
-<div
-  id="root"
->
-  <aside
-    class="info-bar"
-  />
-</div>
-`;