Explorar o código

feat: query tables support both sort and custom properties

Tienson Qin %!s(int64=4) %!d(string=hai) anos
pai
achega
fa17476d13

+ 21 - 11
src/main/frontend/components/block.cljs

@@ -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

+ 4 - 0
src/main/frontend/components/block.css

@@ -427,3 +427,7 @@ a:hover > .bullet-container .bullet {
 a.filter svg {
   transform: scale(0.9);
 }
+
+.table-query-properties svg {
+    display: inline;
+}

+ 85 - 74
src/main/frontend/components/query_table.cljs

@@ -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
+  [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
+                           (:block/created-at item)
+                           :updated-at
+                           (:block/updated-at item)
+                           :block
+                           (:block/content item)
                            :page
-                           [:string (or (:block/original-name item)
-                                        (:block/name item))]
+                           (: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)]))
+                             :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))]
+                             :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))]
+                             :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)))))))]))]))]]))
+                             [: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)))))))]))]))]])))

+ 16 - 0
src/main/frontend/handler/editor.cljs

@@ -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)

+ 52 - 9
src/main/frontend/handler/events.cljs

@@ -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]

+ 1 - 1
src/main/frontend/ui.cljs

@@ -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}

+ 1 - 1
src/main/frontend/util/property.cljs

@@ -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?