Procházet zdrojové kódy

Merge branch 'master' into enhance/mobile-silk

charlie před 3 měsíci
rodič
revize
ebc14a51f7

+ 1 - 1
deps/common/src/logseq/common/util.cljs

@@ -250,7 +250,7 @@
   {:malli/schema [:=> [:cat :any :string] [:or :nil :string [:vector [:maybe :string]]]]}
   [pattern s]
   (when-not (string? s)
-       ;; TODO: sentry
+    ;; TODO: sentry
     (js/console.trace))
   (when (string? s)
     (re-find pattern s)))

+ 6 - 14
deps/db/src/logseq/db/common/entity_plus.cljc

@@ -99,7 +99,9 @@
              ;; replace block id refs if there're cycle references of blocks
                refs (:block/refs e)
                result' (if (and (string? result) refs)
-                         (db-content/id-ref->title-ref result refs)
+                         (db-content/id-ref->title-ref result refs
+                                                       {:db db
+                                                        :replace-pages-with-same-name? false})
                          result)]
            (or result' default-value))
          (lookup-entity e k default-value))))))
@@ -160,14 +162,8 @@
            :block.temp/property-keys
            (get-property-keys e)
 
-           ;; cache :block/title
            :block/title
-           (or
-            (:block.temp/cached-title @(.-cache e))
-            (let [title (get-block-title e k default-value)]
-              (vreset! (.-cache e) (assoc @(.-cache e)
-                                          :block.temp/cached-title title))
-              title))
+           (get-block-title e k default-value)
 
            :block/_parent
            (->> (lookup-entity e k default-value)
@@ -188,12 +184,8 @@
 
 (defn- cache-with-kv
   [^js this]
-  (let [v @(.-cache this)
-        v' (if (:block/title v)
-             (assoc v :block/title
-                    (db-content/id-ref->title-ref (:block/title v) (:block/refs this)))
-             v)]
-    (concat (seq v')
+  (let [v @(.-cache this)]
+    (concat (seq v)
             (seq (.-kv this)))))
 
 #?(:org.babashka/nbb

+ 1 - 1
deps/db/src/logseq/db/common/entity_util.cljs

@@ -16,4 +16,4 @@
 (defn page?
   [entity]
   (or (entity-util/page? entity)
-      (file-entity-util/page? entity)))
+      (file-entity-util/page? entity)))

+ 1 - 5
deps/db/src/logseq/db/common/initial_data.cljs

@@ -14,17 +14,13 @@
             [logseq.db.frontend.entity-util :as entity-util]
             [logseq.db.frontend.rules :as rules]))
 
-(defn- get-pages-by-name
-  [db page-name]
-  (d/datoms db :avet :block/name (common-util/page-name-sanity-lc page-name)))
-
 ;; FIXME: For DB graph built-in pages, look up by name -> uuid like
 ;; get-built-in-page instead of this approach which is more error prone
 (defn get-first-page-by-name
   "Return the oldest page's db id for :block/name"
   [db page-name]
   (when (and db (string? page-name))
-    (first (sort (map :e (get-pages-by-name db page-name))))))
+    (first (sort (map :e (entity-util/get-pages-by-name db page-name))))))
 
 (defn get-first-page-by-title
   "Return the oldest page's db id for :block/title"

+ 25 - 15
deps/db/src/logseq/db/frontend/content.cljs

@@ -4,7 +4,8 @@
             [datascript.core :as d]
             [logseq.common.util :as common-util]
             [logseq.common.util.page-ref :as page-ref]
-            [logseq.db.common.entity-util :as common-entity-util]))
+            [logseq.db.common.entity-util :as common-entity-util]
+            [logseq.db.frontend.entity-util :as entity-util]))
 
 ;; [[uuid]]
 (def id-ref-pattern
@@ -40,14 +41,18 @@
 
 (defn id-ref->title-ref
   "Convert id ref backs to page name refs using refs."
-  [content* refs* & {:keys [replace-block-id?]
-                     :or {replace-block-id? false}}]
+  [content* refs* & {:keys [db replace-block-id? replace-pages-with-same-name?]
+                     :or {replace-block-id? false
+                          replace-pages-with-same-name? true}}]
   (when (string? content*)
     (let [refs (if replace-block-id?
-               ;; The caller need to handle situations including
-               ;; mutual references and circle references.
+                 ;; The caller need to handle situations including
+                 ;; mutual references and circle references.
                  refs*
-                 (filter common-entity-util/page? refs*))
+                 (cond->> (filter common-entity-util/page? refs*)
+                   (and db (false? replace-pages-with-same-name?))
+                   (remove (fn [e]
+                             (> (count (entity-util/get-pages-by-name db (:block/title e))) 1)))))
           content (str content*)]
       (if (re-find id-ref-pattern content)
         (reduce
@@ -107,15 +112,20 @@
   [title refs & {:keys [replace-tag?]
                  :or {replace-tag? true}}]
   (assert (string? title))
-  (let [refs' (->>
-               (map
-                (fn [ref]
-                  (if (and (vector? ref) (= :block/uuid (first ref)))
-                    {:block/uuid (second ref)
-                     :block/title (str (first ref))}
-                    ref))
-                refs)
-               sort-refs)]
+  (let [refs' (->> refs
+                   (remove (fn [ref]
+                             ;; remove uuid references since they're introduced to detect multiple pages
+                             ;; that have the same name
+                             (and (map? ref)
+                                  (:block.temp/original-page-name ref)
+                                  (common-util/uuid-string? (:block.temp/original-page-name ref)))))
+                   (map
+                    (fn [ref]
+                      (if (and (vector? ref) (= :block/uuid (first ref)))
+                        {:block/uuid (second ref)
+                         :block/title (str (first ref))}
+                        ref)))
+                   sort-refs)]
     (reduce
      (fn [content {uuid' :block/uuid :block/keys [title] :as block}]
        (let [title' (or (:block.temp/original-page-name block) title)]

+ 7 - 1
deps/db/src/logseq/db/frontend/entity_util.cljs

@@ -1,8 +1,10 @@
 (ns logseq.db.frontend.entity-util
   "Lower level entity util fns for DB graphs"
   (:require [clojure.string :as string]
+            [datascript.core :as d]
             [datascript.db]
-            [datascript.impl.entity :as de])
+            [datascript.impl.entity :as de]
+            [logseq.common.util :as common-util])
   (:refer-clojure :exclude [object?]))
 
 (defn- has-tag?
@@ -86,3 +88,7 @@
   "Built-in page or block"
   [entity]
   (:logseq.property/built-in? entity))
+
+(defn get-pages-by-name
+  [db page-name]
+  (d/datoms db :avet :block/name (common-util/page-name-sanity-lc page-name)))

+ 1 - 1
deps/db/src/logseq/db/frontend/schema.cljs

@@ -37,7 +37,7 @@
          (map (juxt :major :minor)
               [(parse-schema-version x) (parse-schema-version y)])))
 
-(def version (parse-schema-version "65.7"))
+(def version (parse-schema-version "65.8"))
 
 (defn major-version
   "Return a number.

+ 3 - 1
deps/outliner/src/logseq/outliner/core.cljs

@@ -273,7 +273,7 @@
                                    (not= block-title (:block/title block-entity)))
           _ (when (and db-based? page? block-title)
               (outliner-validate/validate-page-title-characters block-title {:node m*}))
-          m* (if (and db-based? page-title-changed? (not (and page? (:block/parent block-entity))))
+          m* (if (and db-based? page-title-changed?)
                (let [_ (outliner-validate/validate-page-title (:block/title m*) {:node m*})
                      page-name (common-util/page-name-sanity-lc (:block/title m*))]
                  (assoc m* :block/name page-name))
@@ -524,6 +524,8 @@
 (defn- get-target-block-page
   [target-block]
   (or
+   (when (ldb/page? target-block)
+     (:db/id target-block))
    (:db/id (:block/page target-block))
    ;; target parent is a page
    (when-let [parent (:block/parent target-block)]

+ 1 - 0
resources/mobile/index.html

@@ -38,6 +38,7 @@ const portal = new MagicPortal(worker);
 <script defer src="./silkhq.js"></script>
 <script defer src="./js/shared.js"></script>
 <script defer src="./js/main.js"></script>
+<script defer src="./js/code-editor.js"></script>
 <script>
   document.addEventListener('DOMContentLoaded', () => {
     window.Capacitor?.Plugins?.SplashScreen?.hide()

+ 9 - 6
src/main/frontend/components/block.cljs

@@ -709,7 +709,7 @@
    All page-names are sanitized except page-name-in-block"
   [state
    {:keys [contents-page? whiteboard-page? other-position? show-unique-title?
-           on-context-menu with-parent?]
+           on-context-menu with-parent? stop-event-propagation?]
     :or {with-parent? true}
     :as config}
    page-entity children label]
@@ -734,6 +734,8 @@
        :on-drag-start (fn [e]
                         (editor-handler/block->data-transfer! page-name e true))
        :on-pointer-down (fn [^js e]
+                          (when stop-event-propagation?
+                            (util/stop-propagation e))
                           (cond
                             (util/link? (.-target e))
                             nil
@@ -2823,7 +2825,7 @@
                                 (or (ldb/inline-tag? (:block/raw-title block) t)
                                     (:logseq.property.class/hide-from-node t)
                                     (contains? hidden-internal-tags (:db/ident t))
-                                    (and (util/mobile?) (= (:db/ident t) :logseq.class/Task))))))
+                                    (and (util/mobile?) (contains? #{:logseq.class/Task :logseq.class/Journal} (:db/ident t)))))))
           popup-opts {:align :end
                       :content-props {:on-click (fn [] (shui/popup-hide!))
                                       :class "w-60"}}
@@ -3882,9 +3884,11 @@
         *navigating-block (get state ::navigating-block)
         navigating-block (rum/react *navigating-block)
         navigated? (and (not= (:block/uuid block) navigating-block) navigating-block)
-        config' (if-let [container-id (::container-id state)]
-                  (assoc config :container-id container-id)
-                  config)]
+        config' (->
+                 (if-let [container-id (::container-id state)]
+                   (assoc config :container-id container-id)
+                   config)
+                 (assoc :block/uuid (:block/uuid block)))]
     (when (:block/uuid block)
       (rum/with-key
         (block-container-inner state repo config' block
@@ -4370,7 +4374,6 @@
         item (or (if loop-linked? item linked-block) item)
         item (dissoc item :block/meta)
         config' (assoc config
-                       :block/uuid (:block/uuid item)
                        :loop-linked? loop-linked?)]
     (when-not (and loop-linked? (:block/name linked-block))
       (rum/with-key (block-container config' item

+ 1 - 1
src/main/frontend/components/block.css

@@ -542,7 +542,7 @@
 }
 
 @container (max-width: 600px) {
-    .time-spent, .positioned-properties.block-right, .view-actions, .ls-page-title .block-tags {
+    .time-spent, .positioned-properties.block-right, .view-actions {
         display: none;
     }
 

+ 55 - 37
src/main/frontend/components/file_based/query_table.cljs

@@ -1,5 +1,6 @@
 (ns frontend.components.file-based.query-table
-  (:require [frontend.components.svg :as svg]
+  (:require [clojure.string :as string]
+            [frontend.components.svg :as svg]
             [frontend.date :as date]
             [frontend.db :as db]
             [frontend.db.query-dsl :as query-dsl]
@@ -22,8 +23,11 @@
   ;; FIXME: Look up by property id if still supporting clock-time
   (let [ks [:block/properties :clock-time]
         result (map (fn [b]
-                      (let [b (block/parse-title-and-body b)]
-                        (assoc-in b ks (or (clock/clock-summary (:block.temp/ast-body b) false) 0))))
+                      (let [b (update (block/parse-title-and-body b)
+                                      :block/properties (fn [properties] (if (map? properties) properties {})))]
+                        (try (assoc-in b ks (or (clock/clock-summary (:block.temp/ast-body b) false) 0))
+                             (catch :default _e
+                               b))))
                     result)]
     (if (every? #(zero? (get-in % ks)) result)
       (map #(medley/dissoc-in % ks) result)
@@ -173,11 +177,45 @@
     ;; string values will attempt to be rendered as pages, falling back to
     ;; inline-text when no page entity is found
     (string? value) (if-let [page (and (string? value) (db/get-page value))]
-                      (page-cp {} page)
+                      (page-cp {:stop-event-propagation? true} page)
                       (inline-text row-block row-format value))
     ;; anything else should just be rendered as provided
     :else value))
 
+(rum/defc table-row
+  [row columns config page? select? *mouse-down? map-inline page-cp ->elem inline-text]
+  (let [format (get row :block/format :markdown)
+        property-separated-by-commas? (partial text/separated-by-commas? (state/get-config))]
+    [:tr.cursor
+     (for [column columns]
+       (let [[cell-format value] (build-column-value row
+                                                     column
+                                                     {:page? page?
+                                                      :->elem ->elem
+                                                      :map-inline map-inline
+                                                      :config config
+                                                      :comma-separated-property? (property-separated-by-commas? column)})]
+         [:td.whitespace-nowrap
+          {:data-key (pr-str column)
+           :on-pointer-down (fn []
+                              (reset! *mouse-down? true)
+                              (reset! select? false))
+           :on-mouse-move (fn [] (reset! select? true))
+           :on-pointer-up (fn []
+                            (when (and @*mouse-down? (not @select?))
+                              (state/sidebar-add-block!
+                               (state/get-current-repo)
+                               (:db/id row)
+                               :block)
+                              (reset! *mouse-down? false)))}
+          (when (some? value)
+            (render-column-value {:row-block row
+                                  :row-format format
+                                  :cell-format cell-format
+                                  :value value}
+                                 page-cp
+                                 inline-text))]))]))
+
 (rum/defcs result-table-v1 < rum/reactive
   (rum/local false ::select?)
   (rum/local false ::mouse-down?)
@@ -186,8 +224,7 @@
         *mouse-down? (::mouse-down? state)
         clock-time-total (when-not page?
                            (->> (map #(get-in % [:block/properties :clock-time] 0) sort-result')
-                                (apply +)))
-        property-separated-by-commas? (partial text/separated-by-commas? (state/get-config))]
+                                (apply +)))]
     [:div.overflow-x-auto {:on-pointer-down (fn [e] (.stopPropagation e))
                            :style {:width "100%"}
                            :class "query-table"}
@@ -202,41 +239,22 @@
             (sortable-title title column sort-state (:block/uuid current-block))))]]
       [:tbody
        (for [row sort-result']
-         (let [format (get row :block/format :markdown)]
-           [:tr.cursor
-            (for [column columns]
-              (let [[cell-format value] (build-column-value row
-                                                            column
-                                                            {:page? page?
-                                                             :->elem ->elem
-                                                             :map-inline map-inline
-                                                             :config config
-                                                             :comma-separated-property? (property-separated-by-commas? column)})]
-                [:td.whitespace-nowrap
-                 {:data-key (pr-str column)
-                  :on-pointer-down (fn []
-                                     (reset! *mouse-down? true)
-                                     (reset! select? false))
-                  :on-mouse-move (fn [] (reset! select? true))
-                  :on-pointer-up (fn []
-                                   (when (and @*mouse-down? (not @select?))
-                                     (state/sidebar-add-block!
-                                      (state/get-current-repo)
-                                      (:db/id row)
-                                      :block-ref)
-                                     (reset! *mouse-down? false)))}
-                 (when (some? value)
-                   (render-column-value {:row-block row
-                                         :row-format format
-                                         :cell-format cell-format
-                                         :value value}
-                                        page-cp
-                                        inline-text))]))]))]]]))
+         (table-row row columns config page? select? *mouse-down? map-inline page-cp ->elem inline-text))]]]))
 
 (rum/defc result-table < rum/reactive
   [config current-block result {:keys [page?] :as options} map-inline page-cp ->elem inline-text]
   (when current-block
-    (let [result' (if page? result (attach-clock-property result))
+    (let [result (map (fn [item]
+                        (if (and (map? item) (:db/id item))
+                          (if-let [entity-title (:block/title (db/entity (:db/id item)))]
+                            (assoc item :block/title entity-title)
+                            (update item :block/title (fn [title]
+                                                        (some-> title
+                                                                (string/replace "$pfts_2lqh>$" "")
+                                                                (string/replace "$<pfts_2lqh$" "")))))
+                          item))
+                      result)
+          result' (if page? result (attach-clock-property result))
           columns (get-columns current-block result' {:page? page?})
           ;; Sort state needs to be in sync between final result and sortable title
           ;; as user needs to know if there result is sorted

+ 1 - 1
src/main/frontend/components/page.cljs

@@ -646,7 +646,7 @@
                                         :preview? preview?})))
                (lsp-pagebar-slot)])
 
-            (when block?
+            (when (and block? (not sidebar?))
               (component-block/breadcrumb {} repo (:block/uuid page) {}))
 
             (when (and db-based? (ldb/library? page))

+ 17 - 16
src/main/frontend/components/property/value.cljs

@@ -746,22 +746,22 @@
                                     node)
                              id (:db/id node)
                              [header label] (if (integer? id)
-                                              (let [node-title (if (seq (:logseq.property/classes property))
-                                                                 (db-content/recur-replace-uuid-in-block-title node)
-                                                                 (block-handler/block-unique-title node))
-                                                    title (subs node-title 0 256)
-                                                    node (or (db/entity id) node)
-                                                    icon (get-node-icon node)
-                                                    header (when-not (db/page? node)
-                                                             (when-let [breadcrumb (state/get-component :block/breadcrumb)]
-                                                               [:div.text-xs.opacity-70
-                                                                (breadcrumb {:search? true} (state/get-current-repo) (:block/uuid node) {})]))
-                                                    label [:div.flex.flex-row.items-center.gap-1
-                                                           (when-not (or (:logseq.property/classes property)
-                                                                         (contains? #{:class :property} (:logseq.property/type property)))
-                                                             (ui/icon icon {:size 14}))
-                                                           [:div title]]]
-                                                [header label])
+                                              (when-let [node-title (if (seq (:logseq.property/classes property))
+                                                                      (db-content/recur-replace-uuid-in-block-title node)
+                                                                      (block-handler/block-unique-title node))]
+                                                (let [title (subs node-title 0 256)
+                                                      node (or (db/entity id) node)
+                                                      icon (get-node-icon node)
+                                                      header (when-not (db/page? node)
+                                                               (when-let [breadcrumb (state/get-component :block/breadcrumb)]
+                                                                 [:div.text-xs.opacity-70
+                                                                  (breadcrumb {:search? true} (state/get-current-repo) (:block/uuid node) {})]))
+                                                      label [:div.flex.flex-row.items-center.gap-1
+                                                             (when-not (or (:logseq.property/classes property)
+                                                                           (contains? #{:class :property} (:logseq.property/type property)))
+                                                               (ui/icon icon {:size 14}))
+                                                             [:div title]]]
+                                                  [header label]))
                                               [nil (:block/title node)])]
                          (assoc node
                                 :header header
@@ -1035,6 +1035,7 @@
              (blocks-container config (ldb/sort-by-order value-block))
              (rum/with-key
                (block-container (assoc config
+                                       :block/uuid (:block/uuid value-block)
                                        :property-default-value? default-value?) value-block)
                (str (:db/id block) "-" (:db/id property) "-" (:db/id value-block)))))]
 

+ 2 - 1
src/main/frontend/components/views.cljs

@@ -293,7 +293,8 @@
         (let [render (fn [block]
                        [:div
                         (inline-title
-                         {:table? true}
+                         {:table? true
+                          :block/uuid (:block/uuid block)}
                          (some->> (:block/title block)
                                   string/trim
                                   string/split-lines

+ 1 - 2
src/main/frontend/db/model.cljs

@@ -99,8 +99,7 @@ independent of format as format specific heading characters are stripped"
                 (fn content-matches? [block-content external-content block-id]
                   (let [block (db-utils/entity repo block-id)
                         ref-tags (distinct (concat (:block/tags block) (:block/refs block)))]
-                    (= (-> block-content
-                           (db-content/id-ref->title-ref ref-tags)
+                    (= (-> (db-content/id-ref->title-ref block-content ref-tags)
                            (db-content/content-id-ref->page ref-tags)
                            heading-content->route-name)
                        (string/lower-case external-content))))

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

@@ -167,7 +167,7 @@
 
         (util/electron?)
         ;; fullpath will be encoded
-        (path/prepend-protocol "assets:" full-path)
+        (path/prepend-protocol "file:" full-path)
 
         ;(mobile-util/native-platform?)
         ;(mobile-util/convert-file-src full-path)

+ 4 - 1
src/main/frontend/handler/editor.cljs

@@ -330,10 +330,14 @@
                                       (:custom-query? config))
                                   (not (:ref-query-child? config)))
         has-children? (db/has-children? (:block/uuid current-block))
+        library? (:library? config)
         sibling? (cond
                    ref-query-top-block?
                    false
 
+                   (and library? (ldb/page? current-block))
+                   true
+
                    (boolean? sibling?)
                    sibling?
 
@@ -342,7 +346,6 @@
 
                    :else
                    (not has-children?))
-        library? (:library? config)
         new-block' (if library?
                      (-> new-block
                          (-> (assoc :block/tags #{:logseq.class/Page}

+ 7 - 3
src/main/frontend/handler/page.cljs

@@ -261,8 +261,9 @@
   (fn [chosen-result e]
     (util/stop e)
     (state/clear-editor-action!)
-    (p/let [_ (when-let [id (:block/uuid chosen-result)]
-                (db-async/<get-block (state/get-current-repo) id {:children? false}))
+    (p/let [repo (state/get-current-repo)
+            _ (when-let [id (:block/uuid chosen-result)]
+                (db-async/<get-block repo id {:children? false}))
             chosen-result (if (:block/uuid chosen-result)
                             (db/entity [:block/uuid (:block/uuid chosen-result)])
                             chosen-result)
@@ -278,7 +279,10 @@
                                                   page (date/js-date->journal-title gd)]
                                               [page (db/get-page page)])))
                                         [chosen' chosen-result])
-            ref-text (if (and (de/entity? chosen-result) (not (ldb/page? chosen-result)))
+            datoms (state/<invoke-db-worker :thread-api/datoms repo :avet :block/name (util/page-name-sanity-lc chosen'))
+            multiple-pages-same-name? (> (count datoms) 1)
+            ref-text (if (and (de/entity? chosen-result)
+                              (or multiple-pages-same-name? (not (ldb/page? chosen-result))))
                        (ref/->page-ref (:block/uuid chosen-result))
                        (get-page-ref-text chosen'))
             result (when db-based?

+ 13 - 1
src/main/frontend/worker/db/migrate.cljs

@@ -343,6 +343,17 @@
                      sqlite-create-graph/mark-block-as-built-in))]
     [page]))
 
+(defn- add-missing-page-name
+  [db]
+  (let [pages (d/datoms db :avet :block/name "")]
+    (keep
+     (fn [d]
+       (let [page (d/entity db (:e d))]
+         (when-not (string/blank? (:block/title page))
+           {:db/id (:db/id page)
+            :block/name (common-util/page-name-sanity-lc (:block/title page))})))
+     pages)))
+
 (def schema-version->updates
   "A vec of tuples defining datascript migrations. Each tuple consists of the
    schema version integer and a migration map. A migration map can have keys of :properties, :classes
@@ -354,7 +365,8 @@
    ["65.4" {:fix fix-using-properties-as-tags}]
    ["65.5" {:fix remove-block-order-for-tags}]
    ["65.6" {:fix update-extends-to-cardinality-many}]
-   ["65.7" {:fix add-quick-add-page}]])
+   ["65.7" {:fix add-quick-add-page}]
+   ["65.8" {:fix add-missing-page-name}]])
 
 (let [[major minor] (last (sort (map (comp (juxt :major :minor) db-schema/parse-schema-version first)
                                      schema-version->updates)))]

+ 4 - 3
src/main/frontend/worker/db/validate.cljs

@@ -44,8 +44,9 @@
                                                 (into {}))]
                              [[:db/add (:db/id entity) :logseq.property.table/sized-columns new-value]])
 
-                           (:block.temp/fully-loaded? entity)
-                           [[:db/retract (:db/id entity) :block.temp/fully-loaded?]]
+                           (some (fn [k] (= "block.temp" (namespace k))) (keys entity))
+                           (let [ks (filter (fn [k] (= "block.temp" (namespace k))) (keys entity))]
+                             (mapv (fn [k] [:db/retract (:db/id entity) k]) ks))
                            (and (:block/page entity) (not (:block/parent entity)))
                            [[:db/add (:db/id entity) :block/parent (:db/id (:block/page entity))]]
                            (and (not (:block/page entity)) (not (:block/parent entity)) (not (:block/name entity)))
@@ -82,7 +83,7 @@
                                                 [[:db/retract (:e d) (:a d) (:v d)]]))))))
         tx-data (concat fix-tx-data class-as-properties)]
     (when (seq tx-data)
-      (ldb/transact! conn tx-data {:fix-db? true}))))
+      (d/transact! conn tx-data {:fix-db? true}))))
 
 (defn validate-db
   [conn]

+ 6 - 0
src/main/frontend/worker/db_worker.cljs

@@ -412,6 +412,12 @@
   (when-let [conn (worker-state/get-datascript-conn repo)]
     (apply d/q (first inputs) @conn (rest inputs))))
 
+(def-thread-api :thread-api/datoms
+  [repo & args]
+  (when-let [conn (worker-state/get-datascript-conn repo)]
+    (let [result (apply d/datoms @conn args)]
+      (map (fn [d] [(:e d) (:a d) (:v d) (:tx d) (:added d)]) result))))
+
 (def-thread-api :thread-api/pull
   [repo selector id]
   (when-let [conn (worker-state/get-datascript-conn repo)]

+ 2 - 2
src/test/frontend/worker/commands_test.cljs

@@ -71,7 +71,7 @@
       (let [next-time (get-next-time now month-unit 1)]
         (is (= 1 (in-months next-time))))
       (let [next-time (get-next-time one-month-ago month-unit 1)]
-        (is (= 1 (in-months next-time))))
+        (is (> (in-days next-time) 1)))
       (let [next-time (get-next-time one-month-ago month-unit 3)]
         (is (= 2 (in-months next-time))))
       (let [next-time (get-next-time one-month-ago month-unit 5)]
@@ -117,6 +117,6 @@
       (let [next-time (get-next-time (t/minus now (t/weeks 10)) week-unit 1)]
         (is (= 1 (in-weeks next-time))))
       (let [next-time (get-next-time (t/minus now (t/months 10)) month-unit 1)]
-        (is (= 1 (in-months next-time))))
+        (is (> (in-days next-time) 1)))
       (let [next-time (get-next-time (t/minus now (t/years 10)) year-unit 1)]
         (is (= 1 (in-years next-time)))))))