query_react.cljs 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. (ns frontend.db.query-react
  2. "Custom queries."
  3. (:require [clojure.string :as string]
  4. [clojure.walk :as walk]
  5. [frontend.config :as config]
  6. [frontend.date :as date]
  7. [frontend.db.conn :as conn]
  8. [frontend.db.model :as model]
  9. [frontend.db.react :as react]
  10. [frontend.db.utils :as db-utils]
  11. [frontend.extensions.sci :as sci]
  12. [frontend.state :as state]
  13. [frontend.util :as util]
  14. [lambdaisland.glogi :as log]
  15. [logseq.common.util.page-ref :as page-ref]
  16. [logseq.db :as ldb]
  17. [logseq.db.frontend.inputs :as db-inputs]))
  18. (defn resolve-input
  19. "Wrapper around db-inputs/resolve-input which provides editor-specific state"
  20. ([db input]
  21. (resolve-input db input {}))
  22. ([db input opts]
  23. (db-inputs/resolve-input db
  24. input
  25. (merge {:current-page-fn (fn []
  26. (or (when-let [name-or-uuid (state/get-current-page)]
  27. (if (ldb/db-based-graph? db)
  28. (:block/title (model/get-block-by-uuid name-or-uuid))
  29. name-or-uuid))
  30. (:page (state/get-default-home))
  31. (date/today)))}
  32. opts))))
  33. (defn custom-query-result-transform
  34. [query-result remove-blocks q]
  35. (try
  36. (let [result (db-utils/seq-flatten query-result)
  37. block? (:block/uuid (first result))
  38. result (if block?
  39. (let [result (if (seq remove-blocks)
  40. (let [remove-blocks (set remove-blocks)]
  41. (remove (fn [h]
  42. (contains? remove-blocks (:block/uuid h)))
  43. result))
  44. result)]
  45. (model/with-pages result))
  46. result)
  47. result-transform-fn (:result-transform q)]
  48. (if-let [result-transform (if (keyword? result-transform-fn)
  49. (get-in (state/sub-config) [:query/result-transforms result-transform-fn])
  50. result-transform-fn)]
  51. (if-let [f (sci/eval-string (pr-str result-transform))]
  52. (try
  53. (sci/call-fn f result)
  54. (catch :default e
  55. (log/error :sci/call-error e)
  56. result))
  57. result)
  58. result))
  59. (catch :default e
  60. (log/error :query/failed e))))
  61. (defn- resolve-query
  62. [query]
  63. (let [page-ref? #(and (string? %) (page-ref/page-ref? %))]
  64. (walk/postwalk
  65. (fn [f]
  66. (cond
  67. ;; backward compatible
  68. ;; 1. replace :page/ => :block/
  69. (and (keyword? f) (= "page" (namespace f)))
  70. (keyword "block" (name f))
  71. (and (keyword? f) (contains? #{:block/ref-pages :block/ref-blocks} f))
  72. :block/refs
  73. (and (list? f)
  74. (= (first f) '=)
  75. (= 3 (count f))
  76. (some page-ref? (rest f)))
  77. (let [[x y] (rest f)
  78. [page-ref sym] (if (page-ref? x) [x y] [y x])
  79. page-ref (string/lower-case page-ref)]
  80. (list 'contains? sym (page-ref/get-page-name page-ref)))
  81. (and (vector? f)
  82. (= (first f) 'page-property)
  83. (keyword? (util/nth-safe f 2)))
  84. (update f 2 (fn [k] (keyword (string/replace (name k) "_" "-"))))
  85. :else
  86. f)) query)))
  87. (defn react-query
  88. [repo {:keys [query inputs rules] :as query'} query-opts]
  89. (let [pprint (if config/dev? #(when (state/developer-mode?) (apply prn %&)) (fn [_] nil))
  90. start-time (.now js/performance)]
  91. (when config/dev? (js/console.groupCollapsed "react-query logs:"))
  92. (pprint "================")
  93. (pprint "Use the following to debug your datalog queries:")
  94. (pprint query')
  95. (let [query (resolve-query query)
  96. repo (or repo (state/get-current-repo))
  97. db (conn/get-db repo)
  98. resolve-with (select-keys query-opts [:current-page-fn :current-block-uuid])
  99. resolved-inputs (mapv #(resolve-input db % resolve-with) inputs)
  100. inputs (cond-> resolved-inputs
  101. rules
  102. (conj rules))
  103. k [:custom (or (:query-string query') query') inputs]]
  104. (pprint "inputs (post-resolution):" resolved-inputs)
  105. (pprint "query-opts:" query-opts)
  106. (pprint (str "time elapsed: " (.toFixed (- (.now js/performance) start-time) 2) "ms"))
  107. (when config/dev? (js/console.groupEnd))
  108. [k (apply react/q repo k query-opts query inputs)])))