Skip to content

Commit 5ec35e0

Browse files
authored
Merge pull request #1660 from neotyk/fix/atomic-block-split
Atomic block split
2 parents 4e1e6a0 + b1f5fcb commit 5ec35e0

File tree

11 files changed

+631
-109
lines changed

11 files changed

+631
-109
lines changed

CHANGELOG.md

Lines changed: 193 additions & 0 deletions
Large diffs are not rendered by default.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "Athens",
33
"author": "athensresearch",
4-
"version": "1.0.0-alpha.rtc.3",
4+
"version": "1.0.0-alpha.rtc.4",
55
"description": "An open-source knowledege graph for research and notetaking",
66
"repository": {
77
"type": "git",

src/cljc/athens/common_events/graph/atomic.cljc

Lines changed: 1 addition & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,7 @@
44
3 groups of Graph Ops:
55
* block
66
* page
7-
* shortcut"
8-
(:require
9-
[athens.common-db :as common-db]
10-
[athens.common-events.graph.composite :as composite]
11-
[athens.common.utils :as utils]
12-
[clojure.set :as set]))
7+
* shortcut")
138

149

1510
;; Block Ops
@@ -151,29 +146,3 @@
151146
:op/atomic? true
152147
:op/args {:page-uid page-uid
153148
:index index}})
154-
155-
156-
;; create operation in context, result might not be atomic
157-
158-
(defn build-block-save-op
159-
"Creates `:block/save` op, taking into account context.
160-
So it might be a composite or atomic event, depending if new page link is present and if pages exist."
161-
[db block-uid old-string new-string]
162-
(let [links-in-old (utils/find-page-links old-string)
163-
links-in-new (utils/find-page-links new-string)
164-
link-diff (set/difference links-in-new links-in-old)
165-
new-page-titles (remove #(seq (common-db/get-page-uid-by-title db %))
166-
link-diff)
167-
atomic-pages (when-not (empty? new-page-titles)
168-
(into []
169-
(for [title new-page-titles]
170-
(make-page-new-op title
171-
(utils/gen-block-uid)
172-
(utils/gen-block-uid)))))
173-
atomic-save (make-block-save-op block-uid old-string new-string)
174-
block-save-op (if (empty? atomic-pages)
175-
atomic-save
176-
(composite/make-consequence-op {:op/type :block/save}
177-
(conj atomic-pages
178-
atomic-save)))]
179-
block-save-op))
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
(ns athens.common-events.graph.ops
2+
"Building (including contextual resolution) Graph Ops like a boss."
3+
(:require
4+
[athens.common-db :as common-db]
5+
[athens.common-events.graph.atomic :as atomic]
6+
[athens.common-events.graph.composite :as composite]
7+
[athens.common.utils :as utils]
8+
[clojure.set :as set]))
9+
10+
11+
(defn build-block-save-op
12+
"Creates `:block/save` op, taking into account context.
13+
So it might be a composite or atomic event, depending if new page link is present and if pages exist."
14+
[db block-uid old-string new-string]
15+
(let [links-in-old (utils/find-page-links old-string)
16+
links-in-new (utils/find-page-links new-string)
17+
link-diff (set/difference links-in-new links-in-old)
18+
new-page-titles (remove #(seq (common-db/get-page-uid-by-title db %))
19+
link-diff)
20+
atomic-pages (when-not (empty? new-page-titles)
21+
(into []
22+
(for [title new-page-titles]
23+
(atomic/make-page-new-op title
24+
(utils/gen-block-uid)
25+
(utils/gen-block-uid)))))
26+
atomic-save (atomic/make-block-save-op block-uid old-string new-string)
27+
block-save-op (if (empty? atomic-pages)
28+
atomic-save
29+
(composite/make-consequence-op {:op/type :block/save}
30+
(conj atomic-pages
31+
atomic-save)))]
32+
block-save-op))
33+
34+
35+
(defn build-block-split-op
36+
"Creates `:block/split` composite op, taking into account context."
37+
[db {:keys [parent-uid old-block-uid new-block-uid new-block-order
38+
old-string new-string index]}]
39+
(let [save-block-op (build-block-save-op db
40+
old-block-uid
41+
old-string
42+
(subs new-string 0 index))
43+
new-block-op (atomic/make-block-new-op parent-uid new-block-uid new-block-order)
44+
new-block-save-op (build-block-save-op db
45+
new-block-uid
46+
""
47+
(subs new-string index))
48+
split-block-op (composite/make-consequence-op {:op/type :block/split}
49+
[save-block-op
50+
new-block-op
51+
new-block-save-op])]
52+
split-block-op))

src/cljc/athens/common_events/resolver/atomic.cljc

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@
33
[athens.common-db :as common-db]
44
[athens.common.utils :as utils]
55
#?(:clj [datahike.api :as d]
6-
:cljs [datascript.core :as d])))
6+
:cljs [datascript.core :as d]))
7+
#?(:clj
8+
(:import
9+
clojure.lang.ExceptionInfo)))
710

811

912
(defmulti resolve-atomic-op-to-tx
@@ -20,12 +23,12 @@
2023
new-block {:db/id -1
2124
:block/uid block-uid
2225
:block/string ""
23-
:block/order (inc block-order)
26+
:block/order block-order
2427
:block/open true
2528
:create/time now
2629
:edit/time now}
2730
reindex (concat [new-block]
28-
(common-db/inc-after db [:block/uid parent-uid] block-order))
31+
(common-db/inc-after db [:block/uid parent-uid] (dec block-order)))
2932
tx-data {:block/uid parent-uid
3033
:block/children reindex
3134
:edit/time now}]
@@ -36,7 +39,11 @@
3639
(defmethod resolve-atomic-op-to-tx :block/save
3740
[db {:op/keys [args]}]
3841
(let [{:keys [block-uid new-string old-string]} args
39-
{stored-old-string :block/string} (d/pull db [:block/string] [:block/uid block-uid])]
42+
{stored-old-string :block/string} (try
43+
(d/pull db [:block/string] [:block/uid block-uid])
44+
(catch #?(:clj ExceptionInfo
45+
:cljs js/Error) _ex
46+
{:block/string ""}))]
4047
(if (= stored-old-string old-string)
4148
(let [now (utils/now-ts)
4249
updated-block {:db/id [:block/uid block-uid]
@@ -70,11 +77,8 @@
7077

7178

7279
(defmethod resolve-atomic-op-to-tx :composite/consequence
73-
[db {:op/keys [consequences] :as composite}]
80+
[db {:op/keys [consequences] :as _composite}]
7481
(into []
75-
(for [{:op/keys [atomic?] :as consequence} consequences]
76-
(if atomic?
77-
(first (resolve-atomic-op-to-tx db consequence))
78-
(throw
79-
(ex-info "Composite in composite graph ops not supported, yet."
80-
{:composite composite}))))))
82+
(mapcat (fn [consequence]
83+
(resolve-atomic-op-to-tx db consequence))
84+
consequences)))

src/cljs/athens/events.cljs

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
[athens.common-db :as common-db]
44
[athens.common-events :as common-events]
55
[athens.common-events.graph.atomic :as atomic-graph-ops]
6+
[athens.common-events.graph.ops :as graph-ops]
67
[athens.common-events.resolver :as resolver]
78
[athens.common-events.resolver.atomic :as atomic-resolver]
89
[athens.common.utils :as common.utils]
@@ -900,7 +901,7 @@
900901
block-eid (common-db/e-by-av @db/dsdb :block/uid uid)
901902
do-nothing? (or (not block-eid)
902903
(= old-string new-string))
903-
block-save-op (atomic-graph-ops/build-block-save-op @db/dsdb uid old-string new-string)]
904+
block-save-op (graph-ops/build-block-save-op @db/dsdb uid old-string new-string)]
904905
(js/console.debug ":block/save local?" local?
905906
", do-nothing?" do-nothing?)
906907
(when-not do-nothing?
@@ -959,23 +960,28 @@
959960

960961
(reg-event-fx
961962
:enter/split-block
962-
(fn [_ [_ {:keys [uid value index new-uid embed-id] :as args}]]
963+
(fn [_ [_ {:keys [parent-uid uid new-uid new-order old-string value index embed-id] :as args}]]
963964
(js/console.debug ":enter/split-block" (pr-str args))
964-
(let [local? (not (client/open?))]
965-
(js/console.debug ":enter/split-block local?" local?)
965+
(let [local? (not (client/open?))
966+
split-block-op (graph-ops/build-block-split-op @db/dsdb
967+
{:parent-uid parent-uid
968+
:old-block-uid uid
969+
:new-block-uid new-uid
970+
:new-block-order new-order
971+
:old-string old-string
972+
:new-string value
973+
:index index})]
974+
(js/console.debug ":enter/split-block local?" local? "split-block-op" (pr-str split-block-op))
966975
(if local?
967-
(let [split-block-event (common-events/build-split-block-event -1
968-
uid
969-
value
970-
index
971-
new-uid)
972-
tx (resolver/resolve-event-to-tx @db/dsdb split-block-event)]
976+
(let [tx (atomic-resolver/resolve-atomic-op-to-tx @db/dsdb split-block-op)]
973977
(js/console.debug ":enter/split-block tx:" (pr-str tx))
974978
{:fx [[:dispatch-n [[:transact tx]
975979
[:editing/uid (str new-uid (when embed-id
976980
(str "-embed-" embed-id)))]]]]})
977981

978-
{:fx [[:dispatch [:remote/split-block args]]]}))))
982+
{:fx [[:dispatch [:remote/split-block {:op split-block-op
983+
:new-uid new-uid
984+
:embed-id embed-id}]]]}))))
979985

980986

981987
(reg-event-fx
@@ -1033,13 +1039,15 @@
10331039
(.getAttribute "data-uid"))
10341040
uid)
10351041
[uid embed-id] (db/uid-and-embed-id uid)
1036-
block (db/get-block [:block/uid uid])
1037-
parent (db/get-parent [:block/uid uid])
1042+
{:block/keys [string order]
1043+
:as block} (db/get-block [:block/uid uid])
1044+
{parent-uid :block/uid
1045+
:as parent} (db/get-parent [:block/uid uid])
10381046
is-parent-root-embed? (= (some-> d-key-down :target
10391047
(.. (closest ".block-embed"))
10401048
(. -firstChild)
10411049
(.getAttribute "data-uid"))
1042-
(str (:block/uid parent) "-embed-" embed-id))
1050+
(str parent-uid "-embed-" embed-id))
10431051
root-block? (boolean (:node/title parent))
10441052
context-root-uid (get-in rfdb [:current-route :path-params :id])
10451053
new-uid (common.utils/gen-block-uid)
@@ -1095,11 +1103,14 @@
10951103
:embed-id embed-id}]
10961104

10971105
(not (zero? start))
1098-
[:enter/split-block {:uid uid
1099-
:value value
1100-
:index start
1101-
:new-uid new-uid
1102-
:embed-id embed-id}]
1106+
[:enter/split-block {:uid uid
1107+
:old-string string
1108+
:parent-uid parent-uid
1109+
:value value
1110+
:index start
1111+
:new-uid new-uid
1112+
:new-order (inc order)
1113+
:embed-id embed-id}]
11031114

11041115
(empty? value)
11051116
[:unindent {:uid uid

src/cljs/athens/events/remote.cljs

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -524,29 +524,22 @@
524524

525525
(rf/reg-event-fx
526526
:remote/followup-split-block
527-
(fn [{db :db} [_ {:keys [event-id embed-id] :as args}]]
528-
(js/console.debug ":remote/followup-split-block args" (pr-str args))
529-
(let [{:keys [event]} (get-event-acceptance-info db event-id)
530-
{:keys [new-uid]} (:event/args event)]
531-
(js/console.debug ":remote/followup-split-block new-uid:" new-uid
532-
", embed-id" embed-id)
533-
{:fx [[:dispatch [:editing/uid (str new-uid (when embed-id
534-
(str "-embed-" embed-id)))]]]})))
527+
(fn [_ [_ {:keys [embed-id new-uid]}]]
528+
(js/console.debug ":remote/followup-split-block new-uid:" new-uid
529+
", embed-id:" embed-id)
530+
{:fx [[:dispatch [:editing/uid (str new-uid (when embed-id
531+
(str "-embed-" embed-id)))]]]}))
535532

536533

537534
(rf/reg-event-fx
538535
:remote/split-block
539-
(fn [{db :db} [_ {:keys [uid value index new-uid embed-id] :as args}]]
536+
(fn [{db :db} [_ {:keys [op new-uid embed-id] :as args}]]
540537
(js/console.debug ":remote/split-block args" (pr-str args))
541538
(let [last-seen-tx (:remote/last-seen-tx db)
542539
{event-id :event/id
543-
:as split-block-event} (common-events/build-split-block-event last-seen-tx
544-
uid
545-
value
546-
index
547-
new-uid)
548-
followup-fx [[:dispatch [:remote/followup-split-block {:event-id event-id
549-
:embed-id embed-id}]]]]
540+
:as split-block-event} (common-events/build-atomic-event last-seen-tx op)
541+
followup-fx [[:dispatch [:remote/followup-split-block {:embed-id embed-id
542+
:new-uid new-uid}]]]]
550543
(js/console.debug ":remote/split-block event" (pr-str split-block-event))
551544
{:fx [[:dispatch-n [[:remote/register-followup event-id followup-fx]
552545
[:remote/send-event! split-block-event]]]]})))

0 commit comments

Comments
 (0)