From f6a30f9e0f2c27819fb5721ba72dfb037a4076d6 Mon Sep 17 00:00:00 2001
From: Jack Reed <phillipjreed@gmail.com>
Date: Fri, 14 Feb 2020 16:32:09 -0700
Subject: [PATCH] Update annotations reducer to be able to merge state at the
 canvas level

Fixes #2941

This will support asynchronous annotations from multiple sources for a
canvas. Previously this worked as a last in only out.
---
 __tests__/src/reducers/annotations.test.js | 72 ++++++++++++++++++++++
 src/state/reducers/annotations.js          |  3 +
 2 files changed, 75 insertions(+)

diff --git a/__tests__/src/reducers/annotations.test.js b/__tests__/src/reducers/annotations.test.js
index 762a43d79..7a76ee279 100644
--- a/__tests__/src/reducers/annotations.test.js
+++ b/__tests__/src/reducers/annotations.test.js
@@ -46,6 +46,78 @@ describe('annotation reducer', () => {
       },
     });
   });
+  it('should be able to RECEIVE_ANNOTATION from multiple sources and merge state', () => {
+    const firstReduction = annotationsReducer(
+      {
+        foo: {
+          abc123: {
+            id: 'abc123',
+            isFetching: true,
+          },
+        },
+      },
+      {
+        annotationId: 'efg456',
+        annotationJson: {
+          '@type': 'sc:AnnotationList',
+          content: 'anno stuff',
+          id: 'efg456',
+        },
+        targetId: 'foo',
+        type: ActionTypes.RECEIVE_ANNOTATION,
+      },
+    );
+    expect(firstReduction).toMatchObject({
+      foo: {
+        abc123: {
+          id: 'abc123',
+          isFetching: true,
+        },
+        efg456: {
+          isFetching: false,
+          json: {
+            '@type': 'sc:AnnotationList',
+            content: 'anno stuff',
+            id: 'efg456',
+          },
+        },
+      },
+    });
+    const secondReduction = annotationsReducer(
+      firstReduction,
+      {
+        annotationId: 'abc123',
+        annotationJson: {
+          '@type': 'sc:AnnotationList',
+          content: 'anno stuff',
+          id: 'abc123',
+        },
+        targetId: 'foo',
+        type: ActionTypes.RECEIVE_ANNOTATION,
+      },
+    );
+    expect(secondReduction).toMatchObject({
+      foo: {
+        abc123: {
+          id: 'abc123',
+          isFetching: false,
+          json: {
+            '@type': 'sc:AnnotationList',
+            content: 'anno stuff',
+            id: 'abc123',
+          },
+        },
+        efg456: {
+          isFetching: false,
+          json: {
+            '@type': 'sc:AnnotationList',
+            content: 'anno stuff',
+            id: 'efg456',
+          },
+        },
+      },
+    });
+  });
   it('should handle RECEIVE_ANNOTATION_FAILURE', () => {
     expect(annotationsReducer(
       {
diff --git a/src/state/reducers/annotations.js b/src/state/reducers/annotations.js
index aabbfc88c..57fa265bd 100644
--- a/src/state/reducers/annotations.js
+++ b/src/state/reducers/annotations.js
@@ -9,6 +9,7 @@ export const annotationsReducer = (state = {}, action) => {
       return {
         ...state,
         [action.targetId]: {
+          ...state[action.targetId],
           [action.annotationId]: {
             id: action.annotationId,
             isFetching: true,
@@ -19,6 +20,7 @@ export const annotationsReducer = (state = {}, action) => {
       return {
         ...state,
         [action.targetId]: {
+          ...state[action.targetId],
           [action.annotationId]: {
             id: action.annotationId,
             isFetching: false,
@@ -30,6 +32,7 @@ export const annotationsReducer = (state = {}, action) => {
       return {
         ...state,
         [action.targetId]: {
+          ...state[action.targetId],
           [action.annotationId]: {
             error: action.error,
             id: action.annotationId,
-- 
GitLab