mirror of https://github.com/logseq/logseq
parent
6853acd0c9
commit
22d2c83a91
|
@ -2171,7 +2171,7 @@
|
|||
(query-builder-component/builder (:block/title block)
|
||||
{:block block
|
||||
:query-object? true})
|
||||
(when @*hover?
|
||||
(when (and @*hover? (not (string/blank? (:block/title block))))
|
||||
(shui/button
|
||||
{:variant "outline"
|
||||
:size :sm
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
(rum/defc custom-query-header
|
||||
[{:keys [dsl-query?] :as config}
|
||||
{:keys [title query] :as q}
|
||||
{:keys [collapsed? result table? current-block view-f page-list? query-error-atom fulltext-query-result-atom]}]
|
||||
{:keys [collapsed? result table? current-block view-f page-list? query-error-atom]}]
|
||||
(let [dsl-page-query? (and dsl-query?
|
||||
(false? (:blocks? (query-dsl/parse-query query))))
|
||||
full-text-search? (and dsl-query?
|
||||
|
@ -82,4 +82,4 @@
|
|||
(query-refresh-button query-time {:full-text-search? full-text-search?
|
||||
:on-pointer-down (fn [e]
|
||||
(util/stop e)
|
||||
(query-result/trigger-custom-query! config q query-error-atom fulltext-query-result-atom))}))]])]))
|
||||
(query-result/trigger-custom-query! config q query-error-atom (fn [])))}))]])]))
|
||||
|
|
|
@ -124,46 +124,16 @@
|
|||
(:block/collapsed? current-block)))]
|
||||
collapsed?'))
|
||||
|
||||
(rum/defcs custom-query* < rum/reactive rum/static db-mixins/query
|
||||
(rum/local nil ::query-result-atom)
|
||||
(rum/local nil ::prev-q)
|
||||
{:init (fn [state]
|
||||
(let [[{:keys [dsl-query? db-graph? built-in-query?] :as config}
|
||||
{:keys [collapsed?]}] (:rum/args state)]
|
||||
;; collapsed? not needed for db graphs
|
||||
(when (not db-graph?)
|
||||
(when-not (or built-in-query? dsl-query?)
|
||||
(when collapsed?
|
||||
(editor-handler/collapse-block! (or (:block/uuid (:block config))
|
||||
(:block/uuid config)))))))
|
||||
(assoc state :query-error (atom nil)
|
||||
:fulltext-query-result (atom nil)))}
|
||||
[state {:keys [db-graph? dsl-query? built-in-query?] :as config} {:keys [builder query view collapsed?] :as q}]
|
||||
(let [*prev-q (::prev-q state)
|
||||
*query-result-atom (::query-result-atom state)
|
||||
*query-error (:query-error state)
|
||||
*fulltext-query-result (:fulltext-query-result state)
|
||||
current-block-uuid (or (:block/uuid (:block config))
|
||||
(:block/uuid config))
|
||||
current-block (db/entity [:block/uuid current-block-uuid])
|
||||
;; Get query result
|
||||
collapsed?' (calculate-collapsed? current-block current-block-uuid {:collapsed? (if-not db-graph? collapsed? false)})
|
||||
built-in-collapsed? (and collapsed? built-in-query?)
|
||||
table? (when-not db-graph?
|
||||
(or (get-in current-block [:block/properties :query-table])
|
||||
(and (string? query) (string/ends-with? (string/trim query) "table"))))
|
||||
q-changed? (not= @*prev-q q)
|
||||
result (when (or built-in-collapsed? (not collapsed?'))
|
||||
(or (if q-changed? false @*query-result-atom)
|
||||
(let [result (query-result/get-query-result config q *query-error *fulltext-query-result current-block-uuid {:table? table?})]
|
||||
(reset! *query-result-atom result)
|
||||
result)))
|
||||
_ (when q-changed? (reset! *prev-q q))
|
||||
(rum/defc custom-query* < rum/reactive db-mixins/query
|
||||
[{:keys [*query-error db-graph? dsl-query? built-in-query? table? current-block] :as config}
|
||||
{:keys [builder query view collapsed?] :as q}
|
||||
*result]
|
||||
(let [collapsed?' (:collapsed? config)
|
||||
result (when *result (query-result/get-query-result config q (rum/react *result)))
|
||||
;; Args for displaying query header and results
|
||||
view-fn (if (keyword? view) (get-in (state/sub-config) [:query/views view]) view)
|
||||
view-f (and view-fn (sci/eval-string (pr-str view-fn)))
|
||||
page-list? (and (seq result)
|
||||
(some? (:block/name (first result))))
|
||||
page-list? (and (seq result) (some? (:block/name (first result))))
|
||||
opts {:query-error-atom *query-error
|
||||
:current-block current-block
|
||||
:table? table?
|
||||
|
@ -180,7 +150,6 @@
|
|||
(file-query/custom-query-header config
|
||||
q
|
||||
{:query-error-atom *query-error
|
||||
:fulltext-query-result-atom *fulltext-query-result
|
||||
:current-block current-block
|
||||
:table? table?
|
||||
:view-f view-f
|
||||
|
@ -203,14 +172,50 @@
|
|||
(when-not collapsed?'
|
||||
(custom-query-inner config q opts))]))]))))
|
||||
|
||||
(rum/defc trigger-custom-query
|
||||
[config q]
|
||||
(let [[result set-result!] (rum/use-state nil)]
|
||||
(rum/use-effect!
|
||||
(fn []
|
||||
(query-result/trigger-custom-query! config q (:*query-error config) set-result!))
|
||||
[q])
|
||||
(when (and (util/atom? result) (seq @result))
|
||||
(custom-query* config q result))))
|
||||
|
||||
(rum/defcs custom-query < rum/static
|
||||
[state config q]
|
||||
{:init (fn [state]
|
||||
(let [db-graph? (config/db-based-graph? (state/get-current-repo))
|
||||
[{:keys [dsl-query? built-in-query?] :as config}
|
||||
{:keys [collapsed?]}] (:rum/args state)]
|
||||
;; collapsed? not needed for db graphs
|
||||
(when (not db-graph?)
|
||||
(when-not (or built-in-query? dsl-query?)
|
||||
(when collapsed?
|
||||
(editor-handler/collapse-block! (or (:block/uuid (:block config))
|
||||
(:block/uuid config)))))))
|
||||
(assoc state :query-error (atom nil)))}
|
||||
[state {:keys [built-in-query?] :as config}
|
||||
{:keys [query collapsed?] :as q}]
|
||||
(ui/catch-error
|
||||
(ui/block-error "Query Error:" {:content (:query q)})
|
||||
(ui/lazy-visible
|
||||
(fn []
|
||||
(custom-query* (merge config
|
||||
{:db-graph? (config/db-based-graph? (state/get-current-repo))
|
||||
:built-in-query? (built-in-custom-query? (:title q))})
|
||||
q))
|
||||
{:debug-id q})))
|
||||
(let [*query-error (:query-error state)
|
||||
db-graph? (config/db-based-graph? (state/get-current-repo))
|
||||
current-block-uuid (or (:block/uuid (:block config))
|
||||
(:block/uuid config))
|
||||
current-block (db/entity [:block/uuid current-block-uuid])
|
||||
;; Get query result
|
||||
collapsed?' (calculate-collapsed? current-block current-block-uuid {:collapsed? (if-not db-graph? collapsed? false)})
|
||||
built-in-collapsed? (and collapsed? built-in-query?)
|
||||
table? (when-not db-graph?
|
||||
(or (get-in current-block [:block/properties :query-table])
|
||||
(and (string? query) (string/ends-with? (string/trim query) "table"))))
|
||||
config' (assoc config
|
||||
:db-graph? db-graph?
|
||||
:current-block current-block
|
||||
:current-block-uuid current-block-uuid
|
||||
:collapsed? collapsed?'
|
||||
:table? table?
|
||||
:built-in-query? (built-in-custom-query? (:title q))
|
||||
:*query-error *query-error)]
|
||||
(when (or built-in-collapsed? (not collapsed?'))
|
||||
(trigger-custom-query config' q)))))
|
||||
|
|
|
@ -1,57 +1,51 @@
|
|||
(ns frontend.components.query.result
|
||||
"Query result related functionality for query components"
|
||||
(:require [frontend.db.utils :as db-utils]
|
||||
[frontend.search :as search]
|
||||
(:require [clojure.string :as string]
|
||||
[frontend.db :as db]
|
||||
[frontend.db.query-dsl :as query-dsl]
|
||||
[frontend.db.query-custom :as query-custom]
|
||||
[frontend.db.query-dsl :as query-dsl]
|
||||
[frontend.db.query-react :as query-react]
|
||||
[frontend.state :as state]
|
||||
[logseq.common.util :as common-util]
|
||||
[frontend.util :as util]
|
||||
[clojure.string :as string]
|
||||
[promesa.core :as p]
|
||||
[rum.core :as rum]
|
||||
[frontend.db.utils :as db-utils]
|
||||
[frontend.modules.outliner.tree :as tree]
|
||||
[frontend.template :as template]))
|
||||
[frontend.search :as search]
|
||||
[frontend.state :as state]
|
||||
[frontend.template :as template]
|
||||
[logseq.common.util :as common-util]
|
||||
[promesa.core :as p]))
|
||||
|
||||
(defn trigger-custom-query!
|
||||
[config query *query-error *fulltext-query-result]
|
||||
[config query *query-error set-result!]
|
||||
(let [repo (state/get-current-repo)
|
||||
current-block-uuid (or (:block/uuid (:block config))
|
||||
(:block/uuid config))
|
||||
_ (reset! *query-error nil)
|
||||
query-atom (try
|
||||
(cond
|
||||
(:dsl-query? config)
|
||||
(let [q (:query query)
|
||||
form (common-util/safe-read-string q)]
|
||||
(cond
|
||||
(and (symbol? form)
|
||||
_ (reset! *query-error nil)]
|
||||
(try
|
||||
(cond
|
||||
(:dsl-query? config)
|
||||
(let [q (:query query)
|
||||
form (common-util/safe-read-string q)]
|
||||
(cond
|
||||
(and (symbol? form)
|
||||
;; Queries only containgin template should trigger a query
|
||||
(not (re-matches template/template-re (string/trim q))))
|
||||
(atom nil)
|
||||
(not (re-matches template/template-re (string/trim q))))
|
||||
nil
|
||||
|
||||
(re-matches #"\".*\"" q) ; full-text search
|
||||
(do
|
||||
(p/let [blocks (search/block-search repo (string/trim form) {:limit 30})]
|
||||
(when (seq blocks)
|
||||
(let [result (->> blocks
|
||||
(keep (fn [b]
|
||||
(when-not (= (:block/uuid b) current-block-uuid)
|
||||
(db/entity [:block/uuid (:block/uuid b)])))))]
|
||||
(reset! *fulltext-query-result result))))
|
||||
*fulltext-query-result)
|
||||
(re-matches #"\".*\"" q) ; full-text search
|
||||
(p/let [blocks (search/block-search repo (string/trim form) {:limit 30})]
|
||||
(when (seq blocks)
|
||||
(let [result (->> blocks
|
||||
(keep (fn [b]
|
||||
(when-not (= (:block/uuid b) current-block-uuid)
|
||||
(db/entity [:block/uuid (:block/uuid b)])))))]
|
||||
(set-result! (atom result)))))
|
||||
|
||||
:else
|
||||
(query-dsl/query (state/get-current-repo) q {:cards? (:cards? config)})))
|
||||
:else
|
||||
(set-result! (query-dsl/query (state/get-current-repo) q {:cards? (:cards? config)}))))
|
||||
|
||||
:else
|
||||
(query-custom/custom-query query {:current-block-uuid current-block-uuid}))
|
||||
(catch :default e
|
||||
(reset! *query-error e)
|
||||
(atom nil)))]
|
||||
(or query-atom (atom nil))))
|
||||
:else
|
||||
(set-result! (query-custom/custom-query query {:current-block-uuid current-block-uuid})))
|
||||
(catch :default e
|
||||
(reset! *query-error e)))))
|
||||
|
||||
(defn get-group-by-page [{:keys [result-transform query] :as query-m}
|
||||
{:keys [table?]}]
|
||||
|
@ -64,10 +58,8 @@
|
|||
(defn get-query-result
|
||||
"Fetches a query's result, transforms it as needed and saves the result into
|
||||
an atom that is passed in as an argument"
|
||||
[config query-m *query-error *fulltext-query-result current-block-uuid options]
|
||||
(let [query-atom (trigger-custom-query! config query-m *query-error *fulltext-query-result)
|
||||
query-result (and query-atom (rum/react query-atom))
|
||||
;; exclude the current one, otherwise it'll loop forever
|
||||
[{:keys [current-block-uuid table?] :as config} query-m query-result]
|
||||
(let [;; exclude the current one, otherwise it'll loop forever
|
||||
remove-blocks (if current-block-uuid [current-block-uuid] nil)
|
||||
transformed-query-result (when query-result
|
||||
(let [result (query-react/custom-query-result-transform query-result remove-blocks query-m)]
|
||||
|
@ -76,7 +68,7 @@
|
|||
(get query-m :remove-block-children? true)
|
||||
tree/filter-top-level-blocks)
|
||||
result)))
|
||||
group-by-page? (get-group-by-page query-m options)
|
||||
group-by-page? (get-group-by-page query-m {:table? table?})
|
||||
result (if (and group-by-page? (:block/uuid (first transformed-query-result)))
|
||||
(let [result (db-utils/group-by-page transformed-query-result)]
|
||||
(if (map? result)
|
||||
|
@ -85,5 +77,4 @@
|
|||
transformed-query-result)]
|
||||
(when-let [query-result (:query-result config)]
|
||||
(reset! query-result result))
|
||||
(when query-atom
|
||||
(util/safe-with-meta result (meta @query-atom)))))
|
||||
result))
|
||||
|
|
|
@ -1509,13 +1509,6 @@ Arg *stop: atom, reset to true to stop the loop"
|
|||
[pred coll]
|
||||
`(vec (remove ~pred ~coll)))
|
||||
|
||||
#?(:cljs
|
||||
(defn safe-with-meta
|
||||
[o meta]
|
||||
(if (satisfies? IMeta o)
|
||||
(with-meta o meta)
|
||||
o)))
|
||||
|
||||
;; from rum
|
||||
#?(:cljs
|
||||
(def schedule
|
||||
|
|
|
@ -12,7 +12,9 @@
|
|||
(with-redefs [query-custom/custom-query (constantly (atom result))
|
||||
model/with-pages identity]
|
||||
(binding [rum/*reactions* (volatile! #{})]
|
||||
(#'query-result/get-query-result config query-m (atom nil) (atom nil) current-block-uuid {:table? table?}))))
|
||||
(#'query-result/get-query-result (assoc config :table? table? :current-block-uuid current-block-uuid
|
||||
:*query-error (atom nil))
|
||||
query-m))))
|
||||
|
||||
(deftest get-query-result-with-transforms-and-grouping
|
||||
(let [result (mapv
|
||||
|
@ -26,36 +28,36 @@
|
|||
(= expected (mock-get-query-result result query-m {:table? false}))
|
||||
|
||||
;; Default list behavior is to group result
|
||||
{}
|
||||
{{:db/id 1} result}
|
||||
{}
|
||||
{{:db/id 1} result}
|
||||
|
||||
;; User overrides default behavior to return result
|
||||
{:group-by-page? false}
|
||||
result
|
||||
{:group-by-page? false}
|
||||
result
|
||||
|
||||
;; Return transformed result for list view
|
||||
{:result-transform '(partial sort-by :block/scheduled)}
|
||||
sorted-result
|
||||
{:result-transform '(partial sort-by :block/scheduled)}
|
||||
sorted-result
|
||||
|
||||
; User overrides transform to return grouped result
|
||||
{:result-transform '(partial sort-by :block/scheduled) :group-by-page? true}
|
||||
{{:db/id 1} sorted-result})
|
||||
{:result-transform '(partial sort-by :block/scheduled) :group-by-page? true}
|
||||
{{:db/id 1} sorted-result})
|
||||
|
||||
(testing "For table view"
|
||||
(are [query expected]
|
||||
(= expected (mock-get-query-result result query {:table? true}))
|
||||
|
||||
;; Default table behavior is to return result
|
||||
{}
|
||||
result
|
||||
{}
|
||||
result
|
||||
|
||||
;; Return transformed result
|
||||
{:result-transform '(partial sort-by :block/scheduled)}
|
||||
sorted-result
|
||||
{:result-transform '(partial sort-by :block/scheduled)}
|
||||
sorted-result
|
||||
|
||||
;; Ignore override and return normal result
|
||||
{:group-by-page? true}
|
||||
result))
|
||||
{:group-by-page? true}
|
||||
result))
|
||||
|
||||
(testing "current block in results"
|
||||
(is (= result
|
||||
|
|
Loading…
Reference in New Issue