|
|
@@ -2,6 +2,7 @@
|
|
|
(:require [frontend.components.svg :as svg]
|
|
|
[frontend.date :as date]
|
|
|
[frontend.db :as db]
|
|
|
+ [frontend.db.query-dsl :as query-dsl]
|
|
|
[frontend.handler.common :as common-handler]
|
|
|
[frontend.handler.editor :as editor-handler]
|
|
|
[frontend.state :as state]
|
|
|
@@ -13,38 +14,9 @@
|
|
|
[rum.core :as rum]
|
|
|
[frontend.modules.outliner.tree :as tree]))
|
|
|
|
|
|
-;; TODO: extract to table utils
|
|
|
-(defn- sort-result-by
|
|
|
- [by-item desc? result]
|
|
|
- (let [comp (if desc? > <)]
|
|
|
- (sort-by by-item comp result)))
|
|
|
-
|
|
|
-(rum/defc sortable-title
|
|
|
- [title key by-item desc? block-id]
|
|
|
- [:th.whitespace-nowrap
|
|
|
- [:a {:on-click (fn []
|
|
|
- (reset! by-item key)
|
|
|
- (swap! desc? not)
|
|
|
- (when block-id
|
|
|
- (when key
|
|
|
- (editor-handler/set-block-property! block-id :query-sort-by (name key)))
|
|
|
- (editor-handler/set-block-property! block-id :query-sort-desc @desc?)))}
|
|
|
- [:div.flex.items-center
|
|
|
- [:span.mr-1 title]
|
|
|
- (when (= @by-item key)
|
|
|
- [: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 (if page? (distinct (concat keys [:created-at :updated-at])) keys)]
|
|
|
- keys))
|
|
|
-
|
|
|
-(defn attach-clock-property
|
|
|
+;; Util fns
|
|
|
+;; ================
|
|
|
+(defn- attach-clock-property
|
|
|
[result]
|
|
|
(let [ks [:block/properties :clock-time]
|
|
|
result (map (fn [b]
|
|
|
@@ -77,6 +49,64 @@
|
|
|
:else
|
|
|
true))
|
|
|
|
|
|
+(defn- get-sort-state
|
|
|
+ "Return current sort direction and column (item) being sorted, respectively
|
|
|
+ :sort-desc? and :sort-by-item. :sort-by-item is nil if no sorting is to be
|
|
|
+ done"
|
|
|
+ [state current-block]
|
|
|
+ (let [*sort-by-item (get state ::sort-by-item)
|
|
|
+ *desc? (get state ::desc?)
|
|
|
+ p-desc? (get-in current-block [:block/properties :query-sort-desc])
|
|
|
+ desc? (desc? *desc? p-desc?)
|
|
|
+ p-sort-by (keyword (get-in current-block [:block/properties :query-sort-by]))
|
|
|
+ sort-by-item (or @*sort-by-item
|
|
|
+ (some-> p-sort-by keyword)
|
|
|
+ (if (query-dsl/query-contains-filter? (:block/content current-block) "sort-by")
|
|
|
+ nil
|
|
|
+ :updated-at))]
|
|
|
+ {:sort-desc? desc?
|
|
|
+ :sort-by-item sort-by-item}))
|
|
|
+
|
|
|
+(defn- sort-result [result {:keys [sort-by-item sort-desc?]}]
|
|
|
+ (if (some? sort-by-item)
|
|
|
+ (let [comp (if sort-desc? > <)]
|
|
|
+ (sort-by (fn [item]
|
|
|
+ (block/normalize-block (sort-by-fn sort-by-item item)))
|
|
|
+ comp
|
|
|
+ result))
|
|
|
+ result))
|
|
|
+
|
|
|
+;; Components and public fns
|
|
|
+;; =========================
|
|
|
+(rum/defc sortable-title
|
|
|
+ [title key state {:keys [sort-by-item sort-desc?]} block-id]
|
|
|
+ (let [*sort-by-item (get state ::sort-by-item)
|
|
|
+ *desc? (get state ::desc?)]
|
|
|
+ [:th.whitespace-nowrap
|
|
|
+ [:a {:on-click (fn []
|
|
|
+ ;; The two local state atom changes have no effect on
|
|
|
+ ;; preserving state. Consider deleting?
|
|
|
+ (reset! *sort-by-item key)
|
|
|
+ (swap! *desc? not)
|
|
|
+ (editor-handler/set-block-property! block-id :query-sort-by (name key))
|
|
|
+ (editor-handler/set-block-property! block-id :query-sort-desc (not sort-desc?)))}
|
|
|
+ [:div.flex.items-center
|
|
|
+ [:span.mr-1 title]
|
|
|
+ (when (= sort-by-item key)
|
|
|
+ [:span
|
|
|
+ (if sort-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 (if page? (distinct (concat keys [:created-at :updated-at])) keys)]
|
|
|
+ keys))
|
|
|
+
|
|
|
+;; We refer to rows and columns in a table as keys and items.
|
|
|
+;; TODO: Rename key(s) naming as it conflict with core fns
|
|
|
(rum/defcs result-table < rum/reactive
|
|
|
(rum/local nil ::sort-by-item)
|
|
|
(rum/local nil ::desc?)
|
|
|
@@ -84,12 +114,8 @@
|
|
|
[state config current-block result {:keys [page?]} map-inline page-cp ->elem inline-text]
|
|
|
(when current-block
|
|
|
(let [result (tree/filter-top-level-blocks result)
|
|
|
- p-sort-by (keyword (get-in current-block [:block/properties :query-sort-by]))
|
|
|
- p-desc? (get-in current-block [:block/properties :query-sort-desc])
|
|
|
select? (get state ::select?)
|
|
|
- *sort-by-item (get state ::sort-by-item)
|
|
|
- *desc? (get state ::desc?)
|
|
|
- sort-by-item (or @*sort-by-item (some-> p-sort-by keyword) :updated-at)
|
|
|
+ sort-state (get-sort-state state current-block)
|
|
|
;; remove templates
|
|
|
result (remove (fn [b] (some? (get-in b [:block/properties :template]))) result)
|
|
|
result (if page? result (attach-clock-property result))
|
|
|
@@ -108,11 +134,7 @@
|
|
|
(filter included-keys keys)
|
|
|
included-keys)
|
|
|
keys))
|
|
|
- desc? (desc? *desc? p-desc?)
|
|
|
- result (sort-result-by (fn [item]
|
|
|
- (block/normalize-block (sort-by-fn sort-by-item item)))
|
|
|
- desc?
|
|
|
- result)]
|
|
|
+ result (sort-result result sort-state)]
|
|
|
[:div.overflow-x-auto {:on-mouse-down (fn [e] (.stopPropagation e))
|
|
|
:style {:width "100%"}
|
|
|
:class (when-not page? "query-table")}
|
|
|
@@ -124,7 +146,7 @@
|
|
|
(util/format "clock-time(total: %s)" (clock/minutes->days:hours:minutes
|
|
|
clock-time-total))
|
|
|
(name key))]
|
|
|
- (sortable-title key-name key *sort-by-item *desc? (:block/uuid current-block))))]]
|
|
|
+ (sortable-title key-name key state sort-state (:block/uuid current-block))))]]
|
|
|
[:tbody
|
|
|
(for [item result]
|
|
|
(let [format (:block/format item)]
|