1. 21 Sep, 2016 2 commits
    • Robert Knight's avatar
      Move AnnotationSync class to annotator/ dir and remove unused code · e126b97d
      Robert Knight authored
      Now that AnnotationSync is no longer used in the sidebar app, we can
      remove all of the handlers for events and messages arriving through the
      channel which are not needed by the page itself.
      e126b97d
    • Robert Knight's avatar
      Simplify the sidebar app side of sidebar <-> host frame messaging · 55093ebb
      Robert Knight authored
      Previously the communication between the sidebar and host frame was
      implemented by a shared AnnotationSync class, with a 'crossframe'
      service which abstracted the event bus on each side.
      
      This design however assumed that both sides wanted to listen to
      the same messages and react to them in similar ways. This is not
      the case, especially given the change to use Redux for state
      management in the sidebar app.
      
      This commit replaces the crossframe service and AnnotationSync class
      with a new 'frameSync' service which implements only the event
      listeners and sidebar -> page RPC calls that are actually needed.
      
      As a result, local annotation tags for annotations loaded via the API
      can now be assigned by the reducer in the Redux store, making this
      easier to test and getting us another step closer to making Annotation
      objects immutable in the sidebar app.
      55093ebb
  2. 19 Sep, 2016 8 commits
  3. 16 Sep, 2016 4 commits
    • Robert Knight's avatar
      Only save pending updates for annotations in the focused group (#111) · 72859c5e
      Robert Knight authored
      Since we discard all pending updates and deletions when switching
      groups, discard create/update notifications about annotations in
      unfocused groups as soon as we receive them.
      
      This fixes the issue where the 'Apply Update' badge counted updates
      from other groups, with the result that clicking the badge did not
      show any changes.
      72859c5e
    • Robert Knight's avatar
      Move the logic that updates the focused group for new annotations (#108) · 7191e4ba
      Robert Knight authored
      Move the logic that updates the focused group for new annotations
      out of the <annotation> component and into a service.
      
      This fixes the issue where the event handler does not get invoked if no
      <annotation> component instance exists for an annotation because it is
      currently scrolled off-screen.
      
      Fixes #105
      7191e4ba
    • Robert Knight's avatar
      Fix stale copies of annotations being reloaded when switching groups (#110) · ead7c07d
      Robert Knight authored
      Previously when switching groups all of the currently loaded annotations
      would be unloaded and then potentially outdated copies of the annotation
      from the drafts store would be reloaded into the annotation store.
      
      This commit fixes that problem by:
      
       1. Only unloading saved annotations when switching groups.
      
       2. Only storing the annotation ID and tag in the drafts service, to
          ensure that we don't try to use it as a complete annotation anywhere
      
      A consequence of (1) is that new, unsaved annotations no-longer briefly
      disappear when switching groups.
      
      This fixes the problem described in #109 where the orphan status of a
      new annotation is lost when switching groups. It does not fix the
      problem where the new annotation immediately becomes an orphan.
      ead7c07d
    • Robert Knight's avatar
      Fix off-screen empty drafts not being removed when a new annotation is created (#107) · e6746f9a
      Robert Knight authored
      The logic to remove new and empty annotations used to live in the
      <annotation> component because that was the only part of the code that
      had access to the state of unsaved changes.
      
      Since <annotation> instances are only created for on-screen annotations,
      this can result in empty drafts not being removed if the empty
      annotation is off-screen.
      
      Now that the canonical content of unsaved annotations is stored in the
      drafts service, we can move the logic outside of the annotation
      component and fix this problem.
      
      Fixes #97
      e6746f9a
  4. 15 Sep, 2016 14 commits
  5. 14 Sep, 2016 5 commits
    • Robert Knight's avatar
      Add tests for reducer utility functions · 386edd12
      Robert Knight authored
      386edd12
    • Robert Knight's avatar
      Reduce boilerplate in annotationUI for exposing action creators and selectors · 2c70aeba
      Robert Knight authored
      Use helper functions to take the set of action creator and selector
      functions exported by each module and expose them on annotationUI.
      2c70aeba
    • Robert Knight's avatar
      Refactor reducers into a map of action type -> update function · ce7f1330
      Robert Knight authored
      Split the large switch statements in each reducer function
      into objects which map action types to state update functions.
      
      These functions are then composed together with a `createReducer`
      helper defined in `reducers/util`
      ce7f1330
    • Robert Knight's avatar
      Add intro documentation to explain how state management works · f913a4b0
      Robert Knight authored
      For the benefit of developers who are not familiar with Redux and
      Elm-style architectures, add documentation at the top of the
      annotationUI module which explains how state is managed in the app.
      f913a4b0
    • Robert Knight's avatar
      Refactor Redux store · ca72ca9a
      Robert Knight authored
      The `annotationUI` module evolved from before we used Redux to manage
      app state and it was getting large and doing too much. This PR splits
      out most of the logic into smaller modules in the `reducers` folder. The
      `annotationUI` module continues to present the same exports as before to
      avoid needing to change too much in one commit. Each module in `reducers/`
      defines:
      
       - An `init` function which returns the initial state relating to some
         aspect of the application
       - A set of action types, relating to that aspect of the application
       - An `update` function which processes those actions
       - A set of action creators, which are helper functions that create
         these actions
       - A set of selector functions, which are helper functions that return
         derived data from this state
      
      There is a root module in reducers/index.js which combines the actions,
      init function and update functions from each module into a single init
      and update function which can be used to initialize the Redux store.
      
      Action creators which require access to the current app state or are
      asynchronous, such as `addAnnotations` return thunks. See
      https://github.com/gaearon/redux-thunk#motivation . Several
      selection-related action creators currently return thunks but can be
      refactored in future into plain actions.
      
      To avoid making this commit too large, annotationUI continues to export
      wrappers around the action creators so that code outside the Redux store
      and tests do not need to be changed.
      ca72ca9a
  6. 13 Sep, 2016 7 commits