     (let [gen (IdGenerator.getInstance)
           columns [(->InboxColumnSource (.getNextUniqueId gen))
                    (->DocumentColumnSource (.getNextUniqueId gen) 1)
-                   (->DocumentColumnSource (.getNextUniqueId gen) 2)]]
-      {:columns (into {}
-                      (map (juxt :id identity))
-                      columns)}))
+                   (->DocumentColumnSource (.getNextUniqueId gen) 2)
+                   (->DocumentColumnSource (.getNextUniqueId gen) nil)]]
+      {:columns columns}))
   (will-mount [_]
     ;; HACK: Use om/IWillMount to fetch additional data needed by each
     ;; column
-    (doseq [[_ column] (om/get-state owner :columns)]
+    (doseq [column (om/get-state owner :columns)]
       (when (satisfies? om/IWillMount column)
         (om/will-mount column))))
   (render-state [_ {:keys [columns]}]

  (will-mount [_]
    (api/fetch-inbox!)))

(defrecord DocumentColumnSource [id document-id]
  ColumnSource
  (column-title [_ state]
    (get-in state [:documents document-id :title]
            "Untitled Document"))
  (column-pages [_ state]
    (get-in state [:documents document-id :pages]))
  (remove-pages! [_ state page-ids]
    (go
      (if-let [document (om/value (get-in state [:documents document-id]))]
        (<! (api/update-document! (update document
                                          :pages
                                          #(remove (comp (set page-ids) :id) %))))
        (js/console.error (str "[DocumentColumnSource] Failed to get document " document-id)
                          {:document-id document-id}))))
  ColumnDropTarget
  (accept-drop! [_ state new-pages target-idx]
    (go
      (println "dropping" (pr-str (map :id new-pages)) "on document" document-id
               (str "(at index " target-idx ")"))
      (let [document (om/value (get-in state [:documents document-id]))]
        (<! (api/update-document! (update document :pages
                                          (fn [pages]
                                            (data/insert-pages pages
                                                               new-pages
                                                               target-idx)))))
        (println "Saved!")
        ;; indicate successful drop
        true)))
  om/IWillMount
  (will-mount [_]
    (assert (number? document-id))
    (api/fetch-documents! [document-id])))

(defn- inbox-page-drag-over [page owner store-idx! e]
  ;; Calculcate the center position for this image and set idx to the


(defn ^:private inbox-handle-drop! [state owner page-cache target source page-ids target-idx]
  (let [columns (om/get-state owner :columns)
        target  (first (filter #(= (:id %) target) columns))
        source  (first (filter #(= (:id %) source) columns))
        ;; Remove page-ids already in `target'
        existing-pages (mapv :id (column-pages target state))
        pages (into []
