123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135 |
- (ns frontend.db.query-react
- "Custom queries."
- (:require [cljs-time.core :as t]
- [clojure.string :as string]
- [clojure.walk :as walk]
- [frontend.config :as config]
- [frontend.db.model :as model]
- [frontend.db.react :as react]
- [frontend.db.utils :as db-utils :refer [date->int]]
- [frontend.debug :as debug]
- [frontend.extensions.sci :as sci]
- [frontend.state :as state]
- [logseq.graph-parser.text :as text]
- [frontend.util :as util]
- [frontend.date :as date]
- [lambdaisland.glogi :as log]))
- (defn resolve-input
- [input]
- (cond
- (= :right-now-ms input) (util/time-ms)
- (= :start-of-today-ms input) (util/today-at-local-ms 0 0 0 0)
- (= :end-of-today-ms input) (util/today-at-local-ms 24 0 0 0)
- (= :today input)
- (date->int (t/today))
- (= :yesterday input)
- (date->int (t/minus (t/today) (t/days 1)))
- (= :tomorrow input)
- (date->int (t/plus (t/today) (t/days 1)))
- (= :current-page input)
- (some-> (or (state/get-current-page)
- (:page (state/get-default-home))
- (date/today)) string/lower-case)
- (and (keyword? input)
- (util/safe-re-find #"^\d+d(-before)?$" (name input)))
- (let [input (name input)
- days (parse-long (re-find #"^\d+" input))]
- (date->int (t/minus (t/today) (t/days days))))
- (and (keyword? input)
- (util/safe-re-find #"^\d+d(-after)?$" (name input)))
- (let [input (name input)
- days (parse-long (re-find #"^\d+" input))]
- (date->int (t/plus (t/today) (t/days days))))
- (and (string? input) (text/page-ref? input))
- (-> (text/page-ref-un-brackets! input)
- (string/lower-case))
- :else
- input))
- (defn- remove-nested-children-blocks
- [blocks]
- (let [ids (set (map :db/id blocks))]
- (->> blocks
- (remove
- (fn [block]
- (let [id (:db/id (:block/parent block))]
- (contains? ids id)))))))
- (defn custom-query-result-transform
- [query-result remove-blocks q]
- (try
- (let [result (db-utils/seq-flatten query-result)
- block? (:block/uuid (first result))
- result (if block?
- (let [result (if (seq remove-blocks)
- (let [remove-blocks (set remove-blocks)]
- (remove (fn [h]
- (contains? remove-blocks (:block/uuid h)))
- result))
- result)]
- (some->> result
- remove-nested-children-blocks
- (model/sort-by-left-recursive)
- (model/with-pages)))
- result)
- result-transform-fn (:result-transform q)
- repo (state/get-current-repo)]
- (if-let [result-transform (if (keyword? result-transform-fn) (state/sub [:config repo :query/result-transforms result-transform-fn]) result-transform-fn)]
- (if-let [f (sci/eval-string (pr-str result-transform))]
- (try
- (sci/call-fn f result)
- (catch js/Error e
- (log/error :sci/call-error e)
- result))
- result)
- result))
- (catch js/Error e
- (log/error :query/failed e))))
- (defn- resolve-query
- [query]
- (let [page-ref? #(and (string? %) (text/page-ref? %))]
- (walk/postwalk
- (fn [f]
- (cond
- ;; backward compatible
- ;; 1. replace :page/ => :block/
- (and (keyword? f) (= "page" (namespace f)))
- (keyword "block" (name f))
- (and (keyword? f) (contains? #{:block/ref-pages :block/ref-blocks} f))
- :block/refs
- (and (list? f)
- (= (first f) '=)
- (= 3 (count f))
- (some page-ref? (rest f)))
- (let [[x y] (rest f)
- [page-ref sym] (if (page-ref? x) [x y] [y x])
- page-ref (string/lower-case page-ref)]
- (list 'contains? sym (text/page-ref-un-brackets! page-ref)))
- :else
- f)) query)))
- (defn react-query
- [repo {:keys [query inputs rules] :as query'} query-opts]
- (let [pprint (if config/dev? (fn [_] nil) debug/pprint)]
- (pprint "================")
- (pprint "Use the following to debug your datalog queries:")
- (pprint query')
- (let [query (resolve-query query)
- resolved-inputs (mapv resolve-input inputs)
- inputs (cond-> resolved-inputs
- rules
- (conj rules))
- repo (or repo (state/get-current-repo))
- k [:custom query']]
- (pprint "inputs (post-resolution):" resolved-inputs)
- (pprint "query-opts:" query-opts)
- (apply react/q repo k query-opts query inputs))))
|