瀏覽代碼

feat: add :block/path-ref-pages to enable flexible queries

Tienson Qin 4 年之前
父節點
當前提交
f9e9333977

+ 28 - 25
src/main/frontend/components/block.cljs

@@ -1506,18 +1506,18 @@
                          (text/build-data-value refs))]
     [:div.ls-block.flex.flex-col.rounded-sm
      (cond->
-         {:id block-id
-          :data-refs data-refs
-          :data-refs-self data-refs-self
-          :style {:position "relative"}
-          :class (str uuid
-                      (when dummy? " dummy")
-                      (when (and collapsed? has-child?) " collapsed")
-                      (when pre-block? " pre-block"))
-          :blockid (str uuid)
-          :repo repo
-          :level level
-          :haschild (str has-child?)}
+      {:id block-id
+       :data-refs data-refs
+       :data-refs-self data-refs-self
+       :style {:position "relative"}
+       :class (str uuid
+                   (when dummy? " dummy")
+                   (when (and collapsed? has-child?) " collapsed")
+                   (when pre-block? " pre-block"))
+       :blockid (str uuid)
+       :repo repo
+       :level level
+       :haschild (str has-child?)}
        (not slide?)
        (merge attrs))
 
@@ -1748,9 +1748,11 @@
             (and (seq result)
                  (or only-blocks? blocks-grouped-by-page?))
             (->hiccup result (cond-> (assoc config
-                                            ;; :editor-box editor/box
                                             :custom-query? true
-                                            :group-by-page? blocks-grouped-by-page?)
+                                            ;; :breadcrumb-show? true
+                                            :group-by-page? blocks-grouped-by-page?
+                                            ;; :ref? true
+)
                                children?
                                (assoc :ref? true))
                       {:style {:margin-top "0.25rem"
@@ -2044,17 +2046,18 @@
      (assoc :class "doc-mode"))
    (if (:group-by-page? config)
      [:div.flex.flex-col
-      (for [[page blocks] blocks]
-        (let [alias? (:page/alias? page)
-              page (db/entity (:db/id page))]
-          [:div.my-2 (cond-> {:key (str "page-" (:db/id page))}
-                       (:ref? config)
-                       (assoc :class "color-level px-7 py-2 rounded"))
-           (ui/foldable
-            [:div
-             (page-cp config page)
-             (when alias? [:span.text-sm.font-medium.opacity-50 " Alias"])]
-            (blocks-container blocks config))]))]
+      (let [blocks (sort-by (comp :page/journal-day first) > blocks)]
+        (for [[page blocks] blocks]
+          (let [alias? (:page/alias? page)
+                page (db/entity (:db/id page))]
+            [:div.my-2 (cond-> {:key (str "page-" (:db/id page))}
+                         (:ref? config)
+                         (assoc :class "color-level px-7 py-2 rounded"))
+             (ui/foldable
+              [:div
+               (page-cp config page)
+               (when alias? [:span.text-sm.font-medium.opacity-50 " Alias"])]
+              (blocks-container blocks config))])))]
      (blocks-container blocks config))])
 
 (comment

+ 28 - 25
src/main/frontend/db/model.cljs

@@ -12,7 +12,6 @@
             [clojure.set :as set]
             [frontend.utf8 :as utf8]
             [frontend.config :as config]
-            [frontend.format.block :as block]
             [cljs.reader :as reader]
             [cljs-time.core :as t]
             [cljs-time.coerce :as tc]
@@ -38,15 +37,14 @@
     ;; (logical OR / 'exists ...' / set union) and two negations, i.e
     ;; (For all ?g in ?Gs p(?e,?g)) <=> NOT(Exists ?g in ?Gs, such that NOT(p(?e, ?g)))
 
-    ;; TODO: benchmark,
-
-    [(matches-all ?e ?a ?vs)
-     [(first ?vs) ?v0]
-     [?e ?a ?v0]
-     (not-join [?e ?vs]
-               [(identity ?vs) [?v ...]]
-               (not-join [?e ?v]
-                         [?e ?a ?v]))]])
+    ;; [(matches-all ?e ?a ?vs)
+    ;;  [(first ?vs) ?v0]
+    ;;  [?e ?a ?v0]
+    ;;  (not-join [?e ?vs]
+    ;;            [(identity ?vs) [?v ...]]
+    ;;            (not-join [?e ?v]
+    ;;                      [?e ?a ?v]))]
+])
 
 (defn transact-files-db!
   ([tx-data]
@@ -388,7 +386,7 @@
 (defn sort-blocks
   [blocks]
   (let [pages-ids (map (comp :db/id :block/page) blocks)
-        pages (db-utils/pull-many '[:db/id :page/name :page/original-name] pages-ids)
+        pages (db-utils/pull-many '[:db/id :page/name :page/original-name :page/journal-day] pages-ids)
         pages-map (reduce (fn [acc p] (assoc acc (:db/id p) p)) {} pages)
         blocks (map
                 (fn [block]
@@ -511,7 +509,8 @@
 (defn get-block-parent
   [repo block-id]
   (when-let [conn (conn/get-conn repo)]
-    (d/entity conn [:block/children [:block/uuid block-id]])))
+    (when-let [block (d/entity conn [:block/uuid block-id])]
+      (d/entity conn [:block/children [:block/uuid block-id]]))))
 
 ;; non recursive query
 (defn get-block-parents
@@ -605,12 +604,12 @@
   (when-let [conn (conn/get-conn repo)]
     (let [eid (:db/id (db-utils/entity repo [:block/uuid block-uuid]))]
       (->> (d/q
-             '[:find ?c
-               :in $ ?p %
-               :where (parent ?p ?c)]
-             conn
-             eid
-             rules)
+            '[:find ?c
+              :in $ ?p %
+              :where (parent ?p ?c)]
+            conn
+            eid
+            rules)
            (apply concat)))))
 
 (defn get-block-immediate-children
@@ -733,13 +732,19 @@
     (db-utils/entity [:block/uuid (uuid page-name)])
     (db-utils/entity [:page/name page-name])))
 
+(defn- heading-block?
+  [block]
+  (and
+   (vector? block)
+   (= "Heading" (first block))))
+
 (defn get-page-name
   [file ast]
   ;; headline
   (let [ast (map first ast)]
     (if (string/includes? file "pages/contents.")
       "Contents"
-      (let [first-block (last (first (filter block/heading-block? ast)))
+      (let [first-block (last (first (filter heading-block? ast)))
             property-name (when (and (= "Properties" (ffirst ast))
                                      (not (string/blank? (:title (last (first ast))))))
                             (:title (last (first ast))))
@@ -1259,9 +1264,7 @@
                    [?b :block/ref-pages ?b-ref]
                    [(not= ?p-ref ?b-ref)]
                    [(contains? ?refs ?p-ref)]
-                   [(contains? ?refs ?b-ref)]
-                   ))]
-    (conn/get-conn)
-    rules
-    page-ids)
-  )
+                   [(contains? ?refs ?b-ref)]))]
+       (conn/get-conn)
+       rules
+       page-ids))

+ 1 - 1
src/main/frontend/db/query_dsl.cljs

@@ -148,7 +148,7 @@
                            (string/lower-case))]
          (when (and (not (string/blank? page-name))
                     (some? (db-utils/entity repo [:page/name page-name])))
-           [['?b :block/ref-pages [:page/name page-name]]]))
+           [['?b :block/path-ref-pages [:page/name page-name]]]))
 
        (contains? #{'and 'or 'not} fe)
        (let [clauses (->> (map (fn [form]

+ 78 - 29
src/main/frontend/format/block.cljs

@@ -9,7 +9,9 @@
             [datascript.core :as d]
             [frontend.date :as date]
             [frontend.text :as text]
-            [medley.core :as medley]))
+            [medley.core :as medley]
+            [frontend.state :as state]
+            [frontend.db :as db]))
 
 (defn heading-block?
   [block]
@@ -251,9 +253,9 @@
      (concat title body))
     (let [ref-blocks (remove string/blank? @ref-blocks)]
       (assoc block :ref-blocks (map
-                                 (fn [id]
-                                   [:block/uuid (medley/uuid id)])
-                                 ref-blocks)))))
+                                (fn [id]
+                                  [:block/uuid (medley/uuid id)])
+                                ref-blocks)))))
 
 (defn update-src-pos-meta!
   [{:keys [body] :as block}]
@@ -286,6 +288,43 @@
          (block-keywordize (util/remove-nils block)))
        blocks))
 
+(defn with-path-refs
+  [blocks]
+  (loop [blocks blocks
+         acc []
+         parents []]
+    (if (empty? blocks)
+      acc
+      (let [block (first blocks)
+            cur-level (:block/level block)
+            level-diff (- cur-level
+                          (get (last parents) :block/level 0))
+            [path-refs parents]
+            (cond
+              (zero? level-diff)            ; sibling
+              (let [path-refs (mapcat :block/ref-pages (drop-last parents))
+                    parents (conj (vec (butlast parents)) block)]
+                [path-refs parents])
+
+              (> level-diff 0)              ; child
+              (let [path-refs (mapcat :block/ref-pages parents)]
+                [path-refs (conj parents block)])
+
+              (< level-diff 0)              ; new parent
+              (let [parents (take-while (fn [p] (< (:block/level p) cur-level)) parents)
+                    path-refs (mapcat :block/ref-pages parents)]
+                [path-refs (conj parents block)]))]
+        (recur (rest blocks)
+               (conj acc (assoc block :block/path-ref-pages
+                                (->> path-refs
+                                     (concat (:block/ref-pages block))
+                                     (remove string/blank?)
+                                     (map string/lower-case)
+                                     (distinct)
+                                     (map (fn [p]
+                                            {:page/name p})))))
+               parents)))))
+
 (defn extract-blocks
   [blocks last-pos encoded-content]
   (let [blocks
@@ -361,29 +400,30 @@
             (-> (reverse headings)
                 safe-blocks)))]
     (let [first-block (first blocks)
-          first-block-start-pos (get-in first-block [:block/meta :start-pos])]
-      (if (and
-           (not (string/blank? encoded-content))
-           (or (empty? blocks)
-               (> first-block-start-pos 1)))
-        (cons
-         (merge
-          (let [content (utf8/substring encoded-content 0 first-block-start-pos)
-                uuid (d/squuid)]
-            (->
-             {:uuid uuid
-              :content content
-              :anchor (str uuid)
-              :level 2
-              :meta {:start-pos 0
-                     :end-pos (or first-block-start-pos
-                                  (utf8/length encoded-content))}
-              :body (take-while (fn [block] (not (heading-block? block))) blocks)
-              :pre-block? true}
-             (block-keywordize)))
-          (select-keys first-block [:block/file :block/format :block/page]))
-         blocks)
-        blocks))))
+          first-block-start-pos (get-in first-block [:block/meta :start-pos])
+          blocks (if (and
+                      (not (string/blank? encoded-content))
+                      (or (empty? blocks)
+                          (> first-block-start-pos 1)))
+                   (cons
+                    (merge
+                     (let [content (utf8/substring encoded-content 0 first-block-start-pos)
+                           uuid (d/squuid)]
+                       (->
+                        {:uuid uuid
+                         :content content
+                         :anchor (str uuid)
+                         :level 2
+                         :meta {:start-pos 0
+                                :end-pos (or first-block-start-pos
+                                             (utf8/length encoded-content))}
+                         :body (take-while (fn [block] (not (heading-block? block))) blocks)
+                         :pre-block? true}
+                        (block-keywordize)))
+                     (select-keys first-block [:block/file :block/format :block/page]))
+                    blocks)
+                   blocks)]
+      (with-path-refs blocks))))
 
 (defn- page-with-journal
   [original-page-name]
@@ -408,10 +448,18 @@
            content-length (utf8/length encoded-content)
            blocks (extract-blocks ast content-length encoded-content)
            ref-pages-atom (atom [])
+           parent-ref-pages (->> (db/get-block-parent (state/get-current-repo) uuid)
+                                 :block/path-ref-pages
+                                 (map :db/id))
            blocks (doall
                    (map-indexed
                     (fn [idx {:block/keys [ref-pages ref-blocks meta] :as block}]
-                      (let [block (merge
+                      (let [path-ref-pages (->> ref-pages
+                                                (remove string/blank?)
+                                                (map string/lower-case)
+                                                (map (fn [p] [:page/name p]))
+                                                (concat parent-ref-pages))
+                            block (merge
                                    block
                                    {:block/meta meta
                                     :block/marker (get block :block/marker "nil")
@@ -421,7 +469,8 @@
                                     :block/page page
                                     :block/content (utf8/substring encoded-content
                                                                    (:start-pos meta)
-                                                                   (:end-pos meta))}
+                                                                   (:end-pos meta))
+                                    :block/path-ref-pages path-ref-pages}
                                    ;; Preserve the original block id
                                    (when (zero? idx)
                                      {:block/uuid uuid})

+ 4 - 2
src/main/frontend/handler/extract.cljs

@@ -36,7 +36,8 @@
                    (fn [[page blocks]]
                      (if page
                        (map (fn [block]
-                              (let [block-ref-pages (seq (:block/ref-pages block))]
+                              (let [block-ref-pages (seq (:block/ref-pages block))
+                                    block-path-ref-pages (seq (:block/path-ref-pages block))]
                                 (when block-ref-pages
                                   (swap! ref-pages set/union (set block-ref-pages)))
                                 (-> block
@@ -48,7 +49,8 @@
                                            :block/ref-pages (mapv
                                                              (fn [page]
                                                                (block/page-with-journal page))
-                                                             block-ref-pages)))))
+                                                             block-ref-pages)
+                                           :block/path-ref-pages block-path-ref-pages))))
                             blocks)))
                    (remove nil? pages)))
           pages (doall

+ 1 - 1
src/main/frontend/handler/file.cljs

@@ -192,7 +192,7 @@
          (history/add-history! repo [[path original-content content]])))
      (fn [error]
        (println "Write file failed, path: " path ", content: " content)
-       (js/console.error error)))))
+       (log/error :write/failed error)))))
 
 (defn create!
   ([path]