1. 15 Sep, 2016 10 commits
  2. 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
  3. 13 Sep, 2016 8 commits
    • Robert Knight's avatar
      0.42.0 · 71e95f59
      Robert Knight authored
      71e95f59
    • Robert Knight's avatar
      Update Change Log · ecf45391
      Robert Knight authored
      ecf45391
    • Robert Knight's avatar
      Merge pull request #101 from hypothesis/fix-editor-sort · f59e84b3
      Robert Knight authored
      Add temporary timestamps to new annotations (for sorting)
      f59e84b3
    • Nick Stenning's avatar
      Add temporary timestamps to new annotations (for sorting) · 3b8ea633
      Nick Stenning authored
      Brand new annotations (and page notes) are currently displayed as editor
      widgets in the sidebar alongside all the existing annotation cards. This
      means they need to be sortable.
      
      Sorting by location isn't a problem, because the annotation already
      carries the document location information by the time it gets to
      `addAnnotations`, but sorting by the updated date is, because currently
      the `created` and `updated` fields are only provided when the server
      sends back the saved annotation.
      
      This commit changes that by adding temporary `created` and `updated`
      timestamps to new annotations (those without an ID). These will be
      ignored entirely by the server, and overwritten when the annotation is
      saved.
      
      If for whatever reason `addAnnotations` is called with a new annotation
      that already has these fields, they will not be overwritten.
      
      Fixes (the rest of) #96.
      3b8ea633
    • Robert Knight's avatar
      Merge pull request #100 from hypothesis/fix-unnecessary-sortkey-update · 042dd2f0
      Robert Knight authored
      Don't reset the sortKey unless actually switching tabs
      042dd2f0
    • Nick Stenning's avatar
      Don't reset the sortKey unless actually switching tabs · 2289e1c2
      Nick Stenning authored
      Creating a new annotation or page note would reset the sortKey for the
      sidebar to the default, because doing so can trigger a call to
      `selectTab`.
      
      This change ensures that we shortcut the state update if we're already
      on the correct tab, and don't update `sortKey` in that case.
      2289e1c2
    • Robert Knight's avatar
      Merge pull request #99 from hypothesis/sort-notes-tab · 593ec7c5
      Robert Knight authored
      Sort notes tab by date
      593ec7c5
    • Nick Stenning's avatar
      Sort notes tab by date · 2a11ea12
      Nick Stenning authored
      This commit prevents page notes from being sorted by "Location" (i.e.
      document location), a meaningless property for page notes, which would
      result in them being sorted unpredictably.
      
      Instead, we define a default sort key and a set of allowable sort keys
      for each sidebar tab. When switching between tabs, the sort key is
      updated to the default, and the set of allowable sort keys updated
      depending on the tab.
      
      This results in page notes being sorted (by default) in ascending order
      of their most recent update. Using "updated" rather than "created" is a
      bit dubious, but changing this requires a bit of care to avoid strange
      behaviour on the stream, so I've left that for another time.
      
      N.B. As implemented, the sort key on each tab will be reset to the
      default every time the tab changes. This is less surprising than
      preserving the sort key across tab switches, and doesn't involve any
      requirement to remember system state across tab switches. We can also
      revisit this in the future if it seems wrong.
      
      Fixes #96.
      2a11ea12
  4. 12 Sep, 2016 6 commits
    • Robert Knight's avatar
      0.41.0 · f82c850f
      Robert Knight authored
      f82c850f
    • Robert Knight's avatar
      Update Change Log · a767ba59
      Robert Knight authored
      a767ba59
    • Nick Stenning's avatar
      Merge pull request #93 from hypothesis/thread-list · 8cddfa09
      Nick Stenning authored
      Extract virtualized thread list into its own component
      8cddfa09
    • Robert Knight's avatar
      Simplify styling of quotes for hovered annotations · 81cb27ee
      Robert Knight authored
      Annotation quotes now have a default color of `$grey-7`, so there is no
      need to have an additional selector for when the annotation card is
      hovered.
      81cb27ee
    • Robert Knight's avatar
      Extract the top-level thread list into its own component · 2568a483
      Robert Knight authored
       * Extract thread list into its own component for better encapsulation
         and easier testing
      
       * Rename `annotation-card` to `thread-list__card` and move it to
         the component styling file for `thread-list`.
      
         Unfortunately a couple of visual effects still require it
         to be referenced in annotation.scss
      
       * Remove ng-show hack in thread list
      
         Remove the "ng-show" attribute which was added as a hack for reasons
         which are no longer applicable. See
         https://github.com/hypothesis/h/issues/2642#issuecomment-150629305
         for original context.
      
       * Remove unused js-hover class and the code that supports it
      
         It turns out that this class is no longer referenced in code or
         applicable styling.
      2568a483
    • Robert Knight's avatar
      Fix behavior when there are multiple unsaved annotations (#95) · e9259a97
      Robert Knight authored
      Fix missing initialization of $orphan flag for new annotations and
      properly account for annotations that do not have IDs in ADD_ANNOTATIONS
      and UPDATE_ANCHOR_STATUS actions.
      
       - Fix ADD_ANNOTATIONS action replacing the first existing unsaved
         annotation when a second unsaved annotation is added
       - Fix UPDATE_ANCHOR_STATUS action not matching annotations without
         IDs (ie. new annotations) correctly.
       - Fix $orphan flag not being initialized for new annotations
      
      Fixes #94
      e9259a97
  5. 09 Sep, 2016 2 commits
  6. 08 Sep, 2016 1 commit
  7. 07 Sep, 2016 2 commits
    • Nick Stenning's avatar
      Remove "assertion" GET param from token requests · 22181c80
      Nick Stenning authored
      When fetching a JWT from the server, the client needs to supply the
      session CSRF token in order to prevent third-party pages from being able
      to fetch and use tokens without the user's permission.
      
      Previously, we supplied the CSRF token in an "assertion" GET parameter
      (partially in an attempt to make this look a bit like an OAuth token
      issuance API) but in Pyramid 1.7 this isn't allowed. (This is good:
      allowing the CSRF to be passed as a GET parameter makes it easier to
      construct a cross-domain attack which retrieves a token for the user).
      
      This commit moves the CSRF token into a request header, which works
      because there are only two legitimate situations in which this request
      is made:
      
      - from an embed iframe, which is on the same origin as the service
      - from a Chrome extension iframe, which is permitted to make
        cross-origin XHR requests to URLs specified in the manifest (in our
        case, `<all_urls>`).
      
      Note that we cannot rely on Angular's built-in CSRF support here,
      because it does not operate for cross-domain requests.
      22181c80
    • Nick Stenning's avatar
      Revert "Remove "assertion" GET param from token requests" · 8281804b
      Nick Stenning authored
      This reverts commit e0e23bde. This needs
      more thought, as the X-CSRF-Token header won't currently be set for
      cross-domain requests (such as those made by the extension sidebar).
      8281804b
  8. 06 Sep, 2016 6 commits
    • Robert Knight's avatar
      Merge pull request #89 from hypothesis/remove-assertion-param · 7b4723c8
      Robert Knight authored
      Remove "assertion" GET param from token requests
      7b4723c8
    • Nick Stenning's avatar
      Remove "assertion" GET param from token requests · e0e23bde
      Nick Stenning authored
      When fetching a JWT from the server, the client needs to supply the
      session CSRF token in order to prevent third-party pages from being able
      to fetch and use tokens without the user's permission.
      
      Previously, it was necessary to supply this token in the "assertion" GET
      parameter -- in an attempt to make this look a bit like an OAuth token
      issuance API -- but in Pyramid 1.7 this isn't allowed, and it turns out
      not to be necessary, because Angular's CSRF support retrieves the token
      from an XSRF-TOKEN cookie set in earlier requests and sets the
      X-CSRF-Token request header automatically.
      e0e23bde
    • Nick Stenning's avatar
      0.39.0 · 326b4518
      Nick Stenning authored
      326b4518
    • Nick Stenning's avatar
      7a245eb7
    • Nick Stenning's avatar
      Update CHANGELOG.md · c34d0f56
      Nick Stenning authored
      c34d0f56
    • Robert Knight's avatar
      Preserve local tag and anchoring status flags when annotations are updated (#87) · 1832a97c
      Robert Knight authored
      When receiving annotation updates via the WebSocket, merge the updated
      annotation with the existing local annotation, preserving the local tag
      and anchoring status flags.
      
      This fixes a problem where Annotations would be shown as Orphans after
      an update was received via the WebSocket
      
       * When an annotation update is received, merge the current/new
         versions rather than removing the current version and replacing
         it with the new one.
      
       * Remove mutation of existing annotation in `loadAnnotations()`,
         since the reducer function is now responsible for merging changes
         and triggering UI updates
      1832a97c