Skip to content

Commit

Permalink
Merge pull request #1660 from neotyk/fix/atomic-block-split
Browse files Browse the repository at this point in the history
Atomic block split
  • Loading branch information
neotyk authored Sep 21, 2021
2 parents 4e1e6a0 + b1f5fcb commit 5ec35e0
Show file tree
Hide file tree
Showing 11 changed files with 631 additions and 109 deletions.
193 changes: 193 additions & 0 deletions CHANGELOG.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "Athens",
"author": "athensresearch",
"version": "1.0.0-alpha.rtc.3",
"version": "1.0.0-alpha.rtc.4",
"description": "An open-source knowledege graph for research and notetaking",
"repository": {
"type": "git",
Expand Down
33 changes: 1 addition & 32 deletions src/cljc/athens/common_events/graph/atomic.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,7 @@
3 groups of Graph Ops:
* block
* page
* shortcut"
(:require
[athens.common-db :as common-db]
[athens.common-events.graph.composite :as composite]
[athens.common.utils :as utils]
[clojure.set :as set]))
* shortcut")


;; Block Ops
Expand Down Expand Up @@ -151,29 +146,3 @@
:op/atomic? true
:op/args {:page-uid page-uid
:index index}})


;; create operation in context, result might not be atomic

(defn build-block-save-op
"Creates `:block/save` op, taking into account context.
So it might be a composite or atomic event, depending if new page link is present and if pages exist."
[db block-uid old-string new-string]
(let [links-in-old (utils/find-page-links old-string)
links-in-new (utils/find-page-links new-string)
link-diff (set/difference links-in-new links-in-old)
new-page-titles (remove #(seq (common-db/get-page-uid-by-title db %))
link-diff)
atomic-pages (when-not (empty? new-page-titles)
(into []
(for [title new-page-titles]
(make-page-new-op title
(utils/gen-block-uid)
(utils/gen-block-uid)))))
atomic-save (make-block-save-op block-uid old-string new-string)
block-save-op (if (empty? atomic-pages)
atomic-save
(composite/make-consequence-op {:op/type :block/save}
(conj atomic-pages
atomic-save)))]
block-save-op))
52 changes: 52 additions & 0 deletions src/cljc/athens/common_events/graph/ops.cljc
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
(ns athens.common-events.graph.ops
"Building (including contextual resolution) Graph Ops like a boss."
(:require
[athens.common-db :as common-db]
[athens.common-events.graph.atomic :as atomic]
[athens.common-events.graph.composite :as composite]
[athens.common.utils :as utils]
[clojure.set :as set]))


(defn build-block-save-op
"Creates `:block/save` op, taking into account context.
So it might be a composite or atomic event, depending if new page link is present and if pages exist."
[db block-uid old-string new-string]
(let [links-in-old (utils/find-page-links old-string)
links-in-new (utils/find-page-links new-string)
link-diff (set/difference links-in-new links-in-old)
new-page-titles (remove #(seq (common-db/get-page-uid-by-title db %))
link-diff)
atomic-pages (when-not (empty? new-page-titles)
(into []
(for [title new-page-titles]
(atomic/make-page-new-op title
(utils/gen-block-uid)
(utils/gen-block-uid)))))
atomic-save (atomic/make-block-save-op block-uid old-string new-string)
block-save-op (if (empty? atomic-pages)
atomic-save
(composite/make-consequence-op {:op/type :block/save}
(conj atomic-pages
atomic-save)))]
block-save-op))


(defn build-block-split-op
"Creates `:block/split` composite op, taking into account context."
[db {:keys [parent-uid old-block-uid new-block-uid new-block-order
old-string new-string index]}]
(let [save-block-op (build-block-save-op db
old-block-uid
old-string
(subs new-string 0 index))
new-block-op (atomic/make-block-new-op parent-uid new-block-uid new-block-order)
new-block-save-op (build-block-save-op db
new-block-uid
""
(subs new-string index))
split-block-op (composite/make-consequence-op {:op/type :block/split}
[save-block-op
new-block-op
new-block-save-op])]
split-block-op))
26 changes: 15 additions & 11 deletions src/cljc/athens/common_events/resolver/atomic.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
[athens.common-db :as common-db]
[athens.common.utils :as utils]
#?(:clj [datahike.api :as d]
:cljs [datascript.core :as d])))
:cljs [datascript.core :as d]))
#?(:clj
(:import
clojure.lang.ExceptionInfo)))


(defmulti resolve-atomic-op-to-tx
Expand All @@ -20,12 +23,12 @@
new-block {:db/id -1
:block/uid block-uid
:block/string ""
:block/order (inc block-order)
:block/order block-order
:block/open true
:create/time now
:edit/time now}
reindex (concat [new-block]
(common-db/inc-after db [:block/uid parent-uid] block-order))
(common-db/inc-after db [:block/uid parent-uid] (dec block-order)))
tx-data {:block/uid parent-uid
:block/children reindex
:edit/time now}]
Expand All @@ -36,7 +39,11 @@
(defmethod resolve-atomic-op-to-tx :block/save
[db {:op/keys [args]}]
(let [{:keys [block-uid new-string old-string]} args
{stored-old-string :block/string} (d/pull db [:block/string] [:block/uid block-uid])]
{stored-old-string :block/string} (try
(d/pull db [:block/string] [:block/uid block-uid])
(catch #?(:clj ExceptionInfo
:cljs js/Error) _ex
{:block/string ""}))]
(if (= stored-old-string old-string)
(let [now (utils/now-ts)
updated-block {:db/id [:block/uid block-uid]
Expand Down Expand Up @@ -70,11 +77,8 @@


(defmethod resolve-atomic-op-to-tx :composite/consequence
[db {:op/keys [consequences] :as composite}]
[db {:op/keys [consequences] :as _composite}]
(into []
(for [{:op/keys [atomic?] :as consequence} consequences]
(if atomic?
(first (resolve-atomic-op-to-tx db consequence))
(throw
(ex-info "Composite in composite graph ops not supported, yet."
{:composite composite}))))))
(mapcat (fn [consequence]
(resolve-atomic-op-to-tx db consequence))
consequences)))
49 changes: 30 additions & 19 deletions src/cljs/athens/events.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
[athens.common-db :as common-db]
[athens.common-events :as common-events]
[athens.common-events.graph.atomic :as atomic-graph-ops]
[athens.common-events.graph.ops :as graph-ops]
[athens.common-events.resolver :as resolver]
[athens.common-events.resolver.atomic :as atomic-resolver]
[athens.common.utils :as common.utils]
Expand Down Expand Up @@ -900,7 +901,7 @@
block-eid (common-db/e-by-av @db/dsdb :block/uid uid)
do-nothing? (or (not block-eid)
(= old-string new-string))
block-save-op (atomic-graph-ops/build-block-save-op @db/dsdb uid old-string new-string)]
block-save-op (graph-ops/build-block-save-op @db/dsdb uid old-string new-string)]
(js/console.debug ":block/save local?" local?
", do-nothing?" do-nothing?)
(when-not do-nothing?
Expand Down Expand Up @@ -959,23 +960,28 @@

(reg-event-fx
:enter/split-block
(fn [_ [_ {:keys [uid value index new-uid embed-id] :as args}]]
(fn [_ [_ {:keys [parent-uid uid new-uid new-order old-string value index embed-id] :as args}]]
(js/console.debug ":enter/split-block" (pr-str args))
(let [local? (not (client/open?))]
(js/console.debug ":enter/split-block local?" local?)
(let [local? (not (client/open?))
split-block-op (graph-ops/build-block-split-op @db/dsdb
{:parent-uid parent-uid
:old-block-uid uid
:new-block-uid new-uid
:new-block-order new-order
:old-string old-string
:new-string value
:index index})]
(js/console.debug ":enter/split-block local?" local? "split-block-op" (pr-str split-block-op))
(if local?
(let [split-block-event (common-events/build-split-block-event -1
uid
value
index
new-uid)
tx (resolver/resolve-event-to-tx @db/dsdb split-block-event)]
(let [tx (atomic-resolver/resolve-atomic-op-to-tx @db/dsdb split-block-op)]
(js/console.debug ":enter/split-block tx:" (pr-str tx))
{:fx [[:dispatch-n [[:transact tx]
[:editing/uid (str new-uid (when embed-id
(str "-embed-" embed-id)))]]]]})

{:fx [[:dispatch [:remote/split-block args]]]}))))
{:fx [[:dispatch [:remote/split-block {:op split-block-op
:new-uid new-uid
:embed-id embed-id}]]]}))))


(reg-event-fx
Expand Down Expand Up @@ -1033,13 +1039,15 @@
(.getAttribute "data-uid"))
uid)
[uid embed-id] (db/uid-and-embed-id uid)
block (db/get-block [:block/uid uid])
parent (db/get-parent [:block/uid uid])
{:block/keys [string order]
:as block} (db/get-block [:block/uid uid])
{parent-uid :block/uid
:as parent} (db/get-parent [:block/uid uid])
is-parent-root-embed? (= (some-> d-key-down :target
(.. (closest ".block-embed"))
(. -firstChild)
(.getAttribute "data-uid"))
(str (:block/uid parent) "-embed-" embed-id))
(str parent-uid "-embed-" embed-id))
root-block? (boolean (:node/title parent))
context-root-uid (get-in rfdb [:current-route :path-params :id])
new-uid (common.utils/gen-block-uid)
Expand Down Expand Up @@ -1095,11 +1103,14 @@
:embed-id embed-id}]

(not (zero? start))
[:enter/split-block {:uid uid
:value value
:index start
:new-uid new-uid
:embed-id embed-id}]
[:enter/split-block {:uid uid
:old-string string
:parent-uid parent-uid
:value value
:index start
:new-uid new-uid
:new-order (inc order)
:embed-id embed-id}]

(empty? value)
[:unindent {:uid uid
Expand Down
25 changes: 9 additions & 16 deletions src/cljs/athens/events/remote.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -524,29 +524,22 @@

(rf/reg-event-fx
:remote/followup-split-block
(fn [{db :db} [_ {:keys [event-id embed-id] :as args}]]
(js/console.debug ":remote/followup-split-block args" (pr-str args))
(let [{:keys [event]} (get-event-acceptance-info db event-id)
{:keys [new-uid]} (:event/args event)]
(js/console.debug ":remote/followup-split-block new-uid:" new-uid
", embed-id" embed-id)
{:fx [[:dispatch [:editing/uid (str new-uid (when embed-id
(str "-embed-" embed-id)))]]]})))
(fn [_ [_ {:keys [embed-id new-uid]}]]
(js/console.debug ":remote/followup-split-block new-uid:" new-uid
", embed-id:" embed-id)
{:fx [[:dispatch [:editing/uid (str new-uid (when embed-id
(str "-embed-" embed-id)))]]]}))


(rf/reg-event-fx
:remote/split-block
(fn [{db :db} [_ {:keys [uid value index new-uid embed-id] :as args}]]
(fn [{db :db} [_ {:keys [op new-uid embed-id] :as args}]]
(js/console.debug ":remote/split-block args" (pr-str args))
(let [last-seen-tx (:remote/last-seen-tx db)
{event-id :event/id
:as split-block-event} (common-events/build-split-block-event last-seen-tx
uid
value
index
new-uid)
followup-fx [[:dispatch [:remote/followup-split-block {:event-id event-id
:embed-id embed-id}]]]]
:as split-block-event} (common-events/build-atomic-event last-seen-tx op)
followup-fx [[:dispatch [:remote/followup-split-block {:embed-id embed-id
:new-uid new-uid}]]]]
(js/console.debug ":remote/split-block event" (pr-str split-block-event))
{:fx [[:dispatch-n [[:remote/register-followup event-id followup-fx]
[:remote/send-event! split-block-event]]]]})))
Expand Down
Loading

1 comment on commit 5ec35e0

@vercel
Copy link

@vercel vercel bot commented on 5ec35e0 Sep 21, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.