mirror of https://github.com/logseq/logseq
feat: query tables support both sort and custom properties
parent
5dcb128c7e
commit
fa17476d13
|
@ -2138,16 +2138,26 @@
|
|||
(ui/foldable
|
||||
[:div.custom-query-title
|
||||
title
|
||||
(when (and current-block (not page-list?))
|
||||
(when current-block
|
||||
[:div.flex.flex-row.align-items.mt-2 {:on-mouse-down (fn [e] (util/stop e))}
|
||||
[:span.mr-2.ml-2.text-sm "Table view"]
|
||||
[:div {:style {:margin-top 3}}
|
||||
(ui/toggle table?
|
||||
(fn []
|
||||
(editor-handler/set-block-property! current-block-uuid
|
||||
"query-table"
|
||||
(not table?)))
|
||||
true)]])]
|
||||
(when-not page-list?
|
||||
[:div.flex.flex-row
|
||||
[:div.mx-2 [:span.text-sm "Table view"]]
|
||||
[:div {:style {:margin-top 5}}
|
||||
(ui/toggle table?
|
||||
(fn []
|
||||
(editor-handler/set-block-property! current-block-uuid
|
||||
"query-table"
|
||||
(not table?)))
|
||||
true)]])
|
||||
|
||||
[:a.mx-2.opacity-60.hover:opacity-100.block
|
||||
{:on-click (fn []
|
||||
(let [all-keys (query-table/get-keys result page-list?)]
|
||||
(state/pub-event! [:modal/set-query-properties current-block all-keys])))}
|
||||
[:span.table-query-properties
|
||||
[:span.text-sm.mr-1 "Set properties"]
|
||||
svg/settings-sm]]])]
|
||||
(cond
|
||||
(and (seq result) view-f)
|
||||
(let [result (try
|
||||
|
@ -2160,10 +2170,10 @@
|
|||
(util/hiccup-keywordize result))
|
||||
|
||||
page-list?
|
||||
(query-table/result-table config result {:page? true} map-inline page-cp ->elem inline-text)
|
||||
(query-table/result-table config current-block result {:page? true} map-inline page-cp ->elem inline-text)
|
||||
|
||||
table?
|
||||
(query-table/result-table config result {:page? false} map-inline page-cp ->elem inline-text)
|
||||
(query-table/result-table config current-block result {:page? false} map-inline page-cp ->elem inline-text)
|
||||
|
||||
(and (seq result) (or only-blocks? blocks-grouped-by-page?))
|
||||
(->hiccup result (cond-> (assoc config
|
||||
|
|
|
@ -427,3 +427,7 @@ a:hover > .bullet-container .bullet {
|
|||
a.filter svg {
|
||||
transform: scale(0.9);
|
||||
}
|
||||
|
||||
.table-query-properties svg {
|
||||
display: inline;
|
||||
}
|
||||
|
|
|
@ -7,7 +7,8 @@
|
|||
[frontend.date :as date]
|
||||
[frontend.state :as state]
|
||||
[clojure.string :as string]
|
||||
[frontend.components.svg :as svg]))
|
||||
[frontend.components.svg :as svg]
|
||||
[frontend.handler.common :as common-handler]))
|
||||
|
||||
;; TODO: extract to table utils
|
||||
(defn- sort-result-by
|
||||
|
@ -30,85 +31,95 @@
|
|||
[:span
|
||||
(if @desc? (svg/caret-down) (svg/caret-up))])]]])
|
||||
|
||||
(defn get-keys
|
||||
[result page?]
|
||||
(let [keys (->> (distinct (mapcat keys (map :block/properties result)))
|
||||
(remove property/built-in-properties)
|
||||
(remove #{:template}))
|
||||
keys (if page? (cons :page keys) (cons :block keys))
|
||||
keys (concat keys [:created-at :updated-at])]
|
||||
keys))
|
||||
|
||||
(rum/defcs result-table < rum/reactive
|
||||
(rum/local :updated-at ::sort-by-item)
|
||||
(rum/local true ::desc?)
|
||||
(rum/local false ::select?)
|
||||
[state config result {:keys [select-keys page?]} map-inline page-cp ->elem inline-text]
|
||||
(let [select? (get state ::select?)
|
||||
*sort-by-item (get state ::sort-by-item)
|
||||
*desc? (get state ::desc?)
|
||||
editor-box (get config :editor-box)
|
||||
;; remove templates
|
||||
result (remove (fn [b] (some? (get-in b [:block/properties :template]))) result)
|
||||
all-keys (->> (distinct (mapcat keys (map :block/properties result)))
|
||||
(remove property/built-in-properties))
|
||||
keys (if (seq select-keys) select-keys all-keys)
|
||||
keys (if page? (cons :page keys) (cons :block keys))
|
||||
keys (concat keys [:created-at :updated-at])
|
||||
sort-by-fn (fn [item]
|
||||
(let [key @*sort-by-item]
|
||||
(case key
|
||||
:created-at
|
||||
(:block/created-at item)
|
||||
:updated-at
|
||||
(:block/updated-at item)
|
||||
:block
|
||||
(:block/content item)
|
||||
:page
|
||||
(:block/name item)
|
||||
(get-in item [:block/properties key]))))
|
||||
result (sort-result-by sort-by-fn @*desc? result)]
|
||||
[:div.overflow-x-auto {:on-mouse-down (fn [e] (.stopPropagation e))
|
||||
:style {:width "100%"}}
|
||||
[:table.table-auto
|
||||
(for [key keys]
|
||||
(sortable-title (name key) key *sort-by-item *desc?))
|
||||
(for [item result]
|
||||
(let [format (:block/format item)
|
||||
edit-input-id (str "edit-block-" (:id config) "-" (:block/uuid item))
|
||||
heading-level (:block/heading-level item)]
|
||||
[:tr.cursor
|
||||
(for [key keys]
|
||||
(let [value (case key
|
||||
:page
|
||||
[:string (or (:block/original-name item)
|
||||
(:block/name item))]
|
||||
|
||||
:block ; block title
|
||||
(let [title (:block/title item)]
|
||||
(if (seq title)
|
||||
[:element (->elem :div (map-inline config title))]
|
||||
[:string (:block/content item)]))
|
||||
|
||||
[state config current-block result {:keys [page?]} map-inline page-cp ->elem inline-text]
|
||||
(when current-block
|
||||
(let [select? (get state ::select?)
|
||||
*sort-by-item (get state ::sort-by-item)
|
||||
*desc? (get state ::desc?)
|
||||
editor-box (get config :editor-box)
|
||||
;; remove templates
|
||||
result (remove (fn [b] (some? (get-in b [:block/properties :template]))) result)
|
||||
query-properties (some-> (get-in current-block [:block/properties :query-properties] "")
|
||||
(common-handler/safe-read-string "Parsing query properties failed"))
|
||||
keys (if (seq query-properties)
|
||||
query-properties
|
||||
(get-keys result page?))
|
||||
sort-by-fn (fn [item]
|
||||
(let [key @*sort-by-item]
|
||||
(case key
|
||||
:created-at
|
||||
[:string (when-let [created-at (:block/created-at item)]
|
||||
(date/int->local-time-2 created-at))]
|
||||
|
||||
(:block/created-at item)
|
||||
:updated-at
|
||||
[:string (when-let [updated-at (:block/updated-at item)]
|
||||
(date/int->local-time-2 updated-at))]
|
||||
(:block/updated-at item)
|
||||
:block
|
||||
(:block/content item)
|
||||
:page
|
||||
(:block/name item)
|
||||
(get-in item [:block/properties key]))))
|
||||
result (sort-result-by sort-by-fn @*desc? result)]
|
||||
[:div.overflow-x-auto {:on-mouse-down (fn [e] (.stopPropagation e))
|
||||
:style {:width "100%"}}
|
||||
[:table.table-auto
|
||||
(for [key keys]
|
||||
(sortable-title (name key) key *sort-by-item *desc?))
|
||||
(for [item result]
|
||||
(let [format (:block/format item)
|
||||
edit-input-id (str "edit-block-" (:id config) "-" (:block/uuid item))
|
||||
heading-level (:block/heading-level item)]
|
||||
[:tr.cursor
|
||||
(for [key keys]
|
||||
(let [value (case key
|
||||
:page
|
||||
[:string (or (:block/original-name item)
|
||||
(:block/name item))]
|
||||
|
||||
[:string (get-in item [:block/properties key])])]
|
||||
[:td.whitespace-nowrap {:on-mouse-down (fn [] (reset! select? false))
|
||||
:on-mouse-move (fn [] (reset! select? true))
|
||||
:on-mouse-up (fn []
|
||||
(when-not @select?
|
||||
(state/sidebar-add-block!
|
||||
(state/get-current-repo)
|
||||
(:db/id item)
|
||||
:block-ref
|
||||
{:block item})))}
|
||||
(when value
|
||||
(if (= :element (first value))
|
||||
(second value)
|
||||
(let [value (second value)]
|
||||
(if (coll? value)
|
||||
(let [vals (for [item value]
|
||||
(page-cp {} {:block/name item}))]
|
||||
(interpose [:span ", "] vals))
|
||||
(if (not (string? value))
|
||||
value
|
||||
(if-let [page (db/entity [:block/name (string/lower-case value)])]
|
||||
(page-cp {} page)
|
||||
(inline-text format value)))))))]))]))]]))
|
||||
:block ; block title
|
||||
(let [title (:block/title item)]
|
||||
(if (seq title)
|
||||
[:element (->elem :div (map-inline config title))]
|
||||
[:string (:block/content item)]))
|
||||
|
||||
:created-at
|
||||
[:string (when-let [created-at (:block/created-at item)]
|
||||
(date/int->local-time-2 created-at))]
|
||||
|
||||
:updated-at
|
||||
[:string (when-let [updated-at (:block/updated-at item)]
|
||||
(date/int->local-time-2 updated-at))]
|
||||
|
||||
[:string (get-in item [:block/properties key])])]
|
||||
[:td.whitespace-nowrap {:on-mouse-down (fn [] (reset! select? false))
|
||||
:on-mouse-move (fn [] (reset! select? true))
|
||||
:on-mouse-up (fn []
|
||||
(when-not @select?
|
||||
(state/sidebar-add-block!
|
||||
(state/get-current-repo)
|
||||
(:db/id item)
|
||||
:block-ref
|
||||
{:block item})))}
|
||||
(when value
|
||||
(if (= :element (first value))
|
||||
(second value)
|
||||
(let [value (second value)]
|
||||
(if (coll? value)
|
||||
(let [vals (for [item value]
|
||||
(page-cp {} {:block/name item}))]
|
||||
(interpose [:span ", "] vals))
|
||||
(if (not (string? value))
|
||||
value
|
||||
(if-let [page (db/entity [:block/name (string/lower-case value)])]
|
||||
(page-cp {} page)
|
||||
(inline-text format value)))))))]))]))]])))
|
||||
|
|
|
@ -923,6 +923,22 @@
|
|||
(let [key (keyword key)]
|
||||
(block-property-aux! block-id key value)))
|
||||
|
||||
(defn set-block-query-properties!
|
||||
[block-id all-properties key add?]
|
||||
(when-let [block (db/entity [:block/uuid block-id])]
|
||||
(let [query-properties (-> (get-in block [:block/properties :query-properties] "")
|
||||
(common-handler/safe-read-string "Failed to parse query properties"))
|
||||
query-properties (if (seq query-properties)
|
||||
query-properties
|
||||
all-properties)
|
||||
query-properties (if add?
|
||||
(distinct (conj query-properties key))
|
||||
(remove #{key} query-properties))
|
||||
query-properties (vec query-properties)]
|
||||
(if (seq query-properties)
|
||||
(set-block-property! block-id :query-properties (str query-properties))
|
||||
(remove-block-property! block-id :query-properties)))))
|
||||
|
||||
(defn set-block-timestamp!
|
||||
[block-id key value]
|
||||
(let [key (string/lower-case key)
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
[frontend.util :as util :refer [profile]]
|
||||
[frontend.config :as config]
|
||||
[frontend.handler.notification :as notification]
|
||||
[frontend.handler.common :as common-handler]
|
||||
[frontend.handler.editor :as editor-handler]
|
||||
[frontend.components.encryption :as encryption]
|
||||
[frontend.fs.nfs :as nfs]
|
||||
[frontend.db.conn :as conn]
|
||||
|
@ -14,7 +16,9 @@
|
|||
[frontend.db-schema :as db-schema]
|
||||
[frontend.db :as db]
|
||||
[datascript.core :as d]
|
||||
["semver" :as semver]))
|
||||
["semver" :as semver]
|
||||
[clojure.set :as set]
|
||||
[rum.core :as rum]))
|
||||
|
||||
;; TODO: should we move all events here?
|
||||
|
||||
|
@ -30,8 +34,8 @@
|
|||
"Please make sure that you've installed the logseq app for the repo %s on GitHub. "
|
||||
repo-url)
|
||||
(ui/button
|
||||
"Install Logseq on GitHub"
|
||||
:href (str "https://github.com/apps/" config/github-app-name "/installations/new"))]]
|
||||
"Install Logseq on GitHub"
|
||||
:href (str "https://github.com/apps/" config/github-app-name "/installations/new"))]]
|
||||
:error
|
||||
false))
|
||||
|
||||
|
@ -86,17 +90,56 @@
|
|||
"Grant native filesystem permission for directory: "
|
||||
[:b (config/get-local-dir repo)]]
|
||||
(ui/button
|
||||
"Grant"
|
||||
:class "ui__modal-enter"
|
||||
:on-click (fn []
|
||||
(nfs/check-directory-permission! repo)
|
||||
(close-fn)))])))
|
||||
"Grant"
|
||||
:class "ui__modal-enter"
|
||||
:on-click (fn []
|
||||
(nfs/check-directory-permission! repo)
|
||||
(close-fn)))])))
|
||||
|
||||
(defmethod handle :modal/nfs-ask-permission []
|
||||
(when-let [repo (get-local-repo)]
|
||||
(state/set-modal! (ask-permission repo))))
|
||||
|
||||
(defonce *query-properties (atom {}))
|
||||
(rum/defc query-properties-settings-inner < rum/reactive
|
||||
{:will-unmount (fn [state]
|
||||
(reset! *query-properties {})
|
||||
state)}
|
||||
[block shown-properties all-properties close-fn]
|
||||
(let [query-properties (rum/react *query-properties)]
|
||||
[:div.p-4
|
||||
[:div.font-bold "Properties settings for this query:"]
|
||||
(for [property all-properties]
|
||||
(let [property-value (get query-properties property)
|
||||
shown? (if (nil? property-value)
|
||||
(contains? shown-properties property)
|
||||
property-value)]
|
||||
[:div.flex.flex-row.m-2.justify-between.align-items
|
||||
[:div (name property)]
|
||||
[:div.mt-1 (ui/toggle shown?
|
||||
(fn []
|
||||
(let [value (not shown?)]
|
||||
(swap! *query-properties assoc property value)
|
||||
(editor-handler/set-block-query-properties!
|
||||
(:block/uuid block)
|
||||
all-properties
|
||||
property
|
||||
value)))
|
||||
true)]]))]))
|
||||
|
||||
(defn query-properties-settings
|
||||
[block shown-properties all-properties]
|
||||
(fn [close-fn]
|
||||
(query-properties-settings-inner block shown-properties all-properties close-fn)))
|
||||
|
||||
(defmethod handle :modal/set-query-properties [[_ block all-properties]]
|
||||
(let [block-properties (some-> (get-in block [:block/properties :query-properties])
|
||||
(common-handler/safe-read-string "Parsing query properties failed"))
|
||||
shown-properties (if (seq block-properties)
|
||||
(set block-properties)
|
||||
(set all-properties))
|
||||
shown-properties (set/intersection (set all-properties) shown-properties)]
|
||||
(state/set-modal! (query-properties-settings block shown-properties all-properties))))
|
||||
|
||||
(defmethod handle :after-db-restore [[_ repos]]
|
||||
(mapv (fn [{url :url} repo]
|
||||
|
|
|
@ -446,7 +446,7 @@
|
|||
"exiting" "ease-in duration-200 opacity-100 translate-y-0 sm:scale-100"
|
||||
"exited" "ease-in duration-200 opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95")}
|
||||
[:div.absolute.top-0.right-0.pt-2.pr-2
|
||||
[:button.ui__modal-close
|
||||
[:a.ui__modal-close.opacity-60.hover:opacity-100
|
||||
{:aria-label "Close"
|
||||
:type "button"
|
||||
:on-click close-fn}
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
(def built-in-properties
|
||||
(set/union
|
||||
#{:id :custom-id :background-color :heading :collapsed :created-at :updated-at :last-modified-at :created_at :last_modified_at :query-table}
|
||||
#{:id :custom-id :background-color :heading :collapsed :created-at :updated-at :last-modified-at :created_at :last_modified_at :query-table :query-properties}
|
||||
(set (map keyword config/markers))))
|
||||
|
||||
(defn properties-built-in?
|
||||
|
|
Loading…
Reference in New Issue