浏览代码

Merge branch 'master' into enhance/mobile-silk

charlie 4 月之前
父节点
当前提交
5c3d04ca6d

+ 109 - 89
deps/db/src/logseq/db/common/view.cljs

@@ -156,6 +156,13 @@
   (or (:db/ident property-value-entity)
       (not (contains? db-property-type/closed-value-property-types (:logseq.property/type property-entity)))))
 
+(defn- empty-value?
+  [v]
+  (or (nil? v)
+      (= :logseq.property/empty-placeholder v)
+      (and (string? v) (string/blank? v))
+      (and (coll? v) (empty? v))))
+
 (defn- ^:large-vars/cleanup-todo row-matched?
   [db row filters input]
   (let [or? (:or? filters)
@@ -168,95 +175,108 @@
       (fn [[property-ident operator match]]
         (if (nil? match)
           true
-          (let [value (get row property-ident)
-                value' (cond
-                         (set? value) value
-                         (nil? value) #{}
-                         :else #{value})
-                entity? (de/entity? (first value'))
-                result
-                (case operator
-                  :is
-                  (if (boolean? match)
-                    (= (boolean (get-property-value-content db (get row property-ident))) match)
-                    (cond
-                      (empty? match)
-                      true
-                      (and (empty? match) (empty? value'))
-                      true
-                      :else
-                      (if entity?
-                        (let [property (d/entity db property-ident)]
-                          (if (match-property-value-as-entity? (first value') property)
-                            (boolean (seq (set/intersection (set (map :block/uuid value')) match)))
-                            (boolean (seq (set/intersection (set (map db-property/property-value-content value'))
-                                                            (set (map (comp db-property/property-value-content #(d/entity db [:block/uuid %]))
-                                                                      match)))))))
-                        (boolean (seq (set/intersection (set value') match))))))
-
-                  :is-not
-                  (if (boolean? match)
-                    (not= (boolean (get-property-value-content db (get row property-ident))) match)
-                    (cond
-                      (and (empty? match) (seq value'))
-                      true
-                      (and (seq match) (empty? value'))
-                      true
-                      :else
-                      (if entity?
-                        (let [property (d/entity db property-ident)]
-                          (if (match-property-value-as-entity? (first value') property)
-                            (boolean (empty? (set/intersection (set (map :block/uuid value')) match)))
-                            (boolean (empty? (set/intersection (set (map db-property/property-value-content value'))
-                                                               (set (map (comp db-property/property-value-content #(d/entity db [:block/uuid %]))
-                                                                         match)))))))
-                        (boolean (empty? (set/intersection (set value') match))))))
-
-                  :text-contains
-                  (some (fn [v]
-                          (if-let [property-value (get-property-value-content db v)]
-                            (string/includes? (string/lower-case property-value) (string/lower-case match))
-                            false))
-                        value')
-
-                  :text-not-contains
-                  (not-any? #(string/includes? (str (get-property-value-content db %)) match) value')
-
-                  :number-gt
-                  (if match (some #(> (get-property-value-content db %) match) value') true)
-                  :number-gte
-                  (if match (some #(>= (get-property-value-content db %) match) value') true)
-                  :number-lt
-                  (if match (some #(< (get-property-value-content db %) match) value') true)
-                  :number-lte
-                  (if match (some #(<= (get-property-value-content db %) match) value') true)
-
-                  :between
-                  (if (seq match)
-                    (some (fn [value-entity]
-                            (let [[start end] match
-                                  value (get-property-value-content db value-entity)
-                                  conditions [(if start (<= start value) true)
-                                              (if end (<= value end) true)]]
-                              (if (seq match) (every? true? conditions) true))) value')
-                    true)
-
-                  :date-before
-                  (if match (some #(< (:block/journal-day %) (:block/journal-day match)) value') true)
-
-                  :date-after
-                  (if match (some #(> (:block/journal-day %) (:block/journal-day match)) value') true)
-
-                  :before
-                  (let [search-value (common-util/get-timestamp match)]
-                    (if search-value (<= (get row property-ident) search-value) true))
-
-                  :after
-                  (let [search-value (common-util/get-timestamp match)]
-                    (if search-value (>= (get row property-ident) search-value) true))
-
-                  true)]
-            result)))
+          (boolean
+           (let [value (get row property-ident)
+                 value' (cond
+                          (set? value) value
+                          (nil? value) nil
+                          :else #{value})
+                 entity? (de/entity? (first value'))
+                 result
+                 (case operator
+                   :is
+                   (cond
+                     (boolean? match)
+                     (= (boolean (get-property-value-content db (get row property-ident))) match)
+                     (= :empty match)
+                     (empty-value? value)
+                     (empty? match)
+                     true
+                     (and (empty? match) (empty? value'))
+                     true
+                     :else
+                     (if entity?
+                       (let [property (d/entity db property-ident)]
+                         (if (match-property-value-as-entity? (first value') property)
+                           (boolean (seq (set/intersection (set (map :block/uuid value')) match)))
+                           (boolean (seq (set/intersection (set (map db-property/property-value-content value'))
+                                                           (set (map (comp db-property/property-value-content #(d/entity db [:block/uuid %]))
+                                                                     match)))))))
+                       (boolean (seq (set/intersection (set value') match)))))
+
+                   :is-not
+                   (cond
+                     (boolean? match)
+                     (not= (boolean (get-property-value-content db (get row property-ident))) match)
+                     (= :empty match)
+                     (not (empty-value? value))
+                     (and (empty? match) (seq value'))
+                     true
+                     (and (seq match) (empty? value'))
+                     true
+                     :else
+                     (if entity?
+                       (let [property (d/entity db property-ident)]
+                         (if (match-property-value-as-entity? (first value') property)
+                           (boolean (empty? (set/intersection (set (map :block/uuid value')) match)))
+                           (boolean (empty? (set/intersection (set (map db-property/property-value-content value'))
+                                                              (set (map (comp db-property/property-value-content #(d/entity db [:block/uuid %]))
+                                                                        match)))))))
+                       (boolean (empty? (set/intersection (set value') match)))))
+
+                   :text-contains
+                   (some (fn [v]
+                           (if-let [property-value (get-property-value-content db v)]
+                             (string/includes? (string/lower-case property-value) (string/lower-case match))
+                             false))
+                         value')
+
+                   :text-not-contains
+                   (not-any? #(string/includes? (str (get-property-value-content db %)) match) value')
+
+                   :number-gt
+                   (when value
+                     (if match (some #(> (get-property-value-content db %) match) value') true))
+                   :number-gte
+                   (when value
+                     (if match (some #(>= (get-property-value-content db %) match) value') true))
+                   :number-lt
+                   (when value
+                     (if match (some #(< (get-property-value-content db %) match) value') true))
+                   :number-lte
+                   (when value
+                     (if match (some #(<= (get-property-value-content db %) match) value') true))
+
+                   :between
+                   (if (seq match)
+                     (some (fn [value-entity]
+                             (let [[start end] match
+                                   value (get-property-value-content db value-entity)
+                                   conditions [(if start (<= start value) true)
+                                               (if end (<= value end) true)]]
+                               (if (seq match) (every? true? conditions) true))) value')
+                     true)
+
+                   :date-before
+                   (when value
+                     (if match (some #(< (:block/journal-day %) (:block/journal-day match)) value') true))
+
+                   :date-after
+                   (when value
+                     (if match (some #(> (:block/journal-day %) (:block/journal-day match)) value') true))
+
+                   :before
+                   (when value
+                     (let [search-value (common-util/get-timestamp match)]
+                       (if search-value (<= value search-value) true)))
+
+                   :after
+                   (when value
+                     (let [search-value (common-util/get-timestamp match)]
+                       (if search-value (>= value search-value) true)))
+
+                   true)]
+             result))))
       (:filters filters)))))
 
 (defn- get-exclude-page-ids

+ 6 - 2
src/main/frontend/components/block.cljs

@@ -4391,9 +4391,13 @@
 (rum/defc block-list
   [config blocks]
   (let [[virtualized? _] (rum/use-state (not (or (string/includes? js/window.location.search "?rtc-test=true")
-                                                 (and (:journals? config) (< (count blocks) 50))
+                                                 (if (:journals? config)
+                                                   (< (count blocks) 50)
+                                                   (< (count blocks) 10))
                                                  (and (util/mobile?) (ldb/journal? (:block/page (first blocks))))
-                                                 (:block-children? config))))
+                                                 (and (:block-children? config)
+                                                      ;; zoom-in block's children
+                                                      (not (and (:id config) (= (:id config) (str (:block/uuid (:block/parent (first blocks)))))))))))
         render-item (fn [idx]
                       (let [top? (zero? idx)
                             bottom? (= (dec (count blocks)) idx)

+ 41 - 5
src/main/frontend/components/views.cljs

@@ -980,7 +980,7 @@
    {:value "Custom date"
     :label "Custom date"}])
 
-(rum/defc filter-property < rum/static
+(rum/defc ^:large-vars/cleanup-todo filter-property < rum/static
   [view-entity columns {:keys [data-fns] :as table} opts]
   (let [[property set-property!] (rum/use-state nil)
         [values set-values!] (rum/use-state nil)
@@ -1076,7 +1076,24 @@
                                                              :filters filters'})))})))
                    :else
                    option)]
-      (select/select option))))
+      (if (and property (not (contains? #{:block/created-at :block/updated-at} (:db/ident property))))
+        [:div.flex.flex-col.gap-1.text-sm
+         (select/select option)
+         (shui/button {:variant :ghost :size :sm :class "justify-start"
+                       :on-click (fn []
+                                   (let [filters' (conj (:filters filters) [(:db/ident property) :is :empty])]
+                                     (set-filters! {:or? (:or? filters)
+                                                    :filters filters'})))}
+                      [:span.opacity-75.hover:opacity-100.font-normal.text-sm
+                       "Is Empty"])
+         (shui/button {:variant :ghost :size :sm :class "justify-start"
+                       :on-click (fn []
+                                   (let [filters' (conj (:filters filters) [(:db/ident property) :is-not :empty])]
+                                     (set-filters! {:or? (:or? filters)
+                                                    :filters filters'})))}
+                      [:span.opacity-75.hover:opacity-100.font-normal.text-sm
+                       "Is Not Empty"])]
+        (select/select option)))))
 
 (rum/defc filter-properties < rum/static
   [view-entity columns table opts]
@@ -1111,11 +1128,13 @@
 
 (defn get-property-operators
   [property]
-  (if (datetime-property? property)
+  (if (contains? #{:block/created-at :block/updated-at} (:db/ident property))
     [:before :after]
     (concat
      [:is :is-not]
      (case (:logseq.property/type property)
+       (:datetime)
+       [:before :after]
        (:default :url :node)
        [:text-contains :text-not-contains]
        (:date)
@@ -1281,8 +1300,22 @@
                                         many?
                                         (assoc
                                          :multiple-choices? true
-                                         :selected-choices value))]
-                           (select/select option)))
+                                         :selected-choices (when (coll? value) value)))]
+                           (if (and (contains? #{:is :is-not} operator)
+                                    (not (contains? #{:block/created-at :block/updated-at} (:db/ident property))))
+                             [:div.flex.flex-col.gap-1
+                              (select/select option)
+                              (shui/button {:variant :ghost :size :sm :class "justify-start"
+                                            :on-click (fn []
+                                                        (let [new-filters (update filters :filters
+                                                                                  (fn [col]
+                                                                                    (update col idx
+                                                                                            (fn [[property operator _value]]
+                                                                                              [property operator :empty]))))]
+                                                          (set-filters! new-filters)))}
+                                           [:span.opacity-75.hover:opacity-100.font-normal.text-sm
+                                            "Empty"])]
+                             (select/select option))))
                        {:align :start})))}
        (let [value (cond
                      (uuid? value)
@@ -1306,6 +1339,9 @@
             (boolean? value)
             [:div (str value)]
 
+            (= value :empty)
+            [:div "Empty"]
+
             (seq value)
             (->> (map (fn [v] [:div (get-property-value-content v)]) value)
                  (interpose [:div "or"]))

+ 4 - 0
src/main/frontend/worker/db/validate.cljs

@@ -57,6 +57,10 @@
                            [[:db/add (:db/id entity) :logseq.property.class/extends :logseq.class/Root]]
                            (and (or (ldb/class? entity) (ldb/property? entity)) (ldb/internal-page? entity))
                            [[:db/retract (:db/id entity) :block/tags :logseq.class/Page]]
+
+                           (and (:logseq.property.asset/remote-metadata entity) (nil? (:logseq.property.asset/type entity)))
+                           [[:db/retractEntity (:db/id entity)]]
+
                            :else
                            nil)))
                      errors)

+ 7 - 5
src/main/frontend/worker/rtc/asset.cljs

@@ -140,11 +140,13 @@
                                                       repo (str asset-uuid) asset-type checksum url))]
              (when (:ex-data r)
                (throw (ex-info "upload asset failed" r)))
-             (d/transact! conn
-                          [{:block/uuid asset-uuid
-                            :logseq.property.asset/remote-metadata {:checksum checksum :type asset-type}}]
-                       ;; Don't generate rtc ops again, (block-ops & asset-ops)
-                          {:persist-op? false})
+             ;; asset might be deleted by the user before uploaded successfully
+             (when (d/entity @conn [:block/uuid asset-uuid])
+               (d/transact! conn
+                            [{:block/uuid asset-uuid
+                              :logseq.property.asset/remote-metadata {:checksum checksum :type asset-type}}]
+                            ;; Don't generate rtc ops again, (block-ops & asset-ops)
+                            {:persist-op? false}))
              (client-op/remove-asset-op repo asset-uuid))))
        (c.m/concurrent-exec-flow 3 (m/seed asset-uuid->url))
        (m/reduce (constantly nil))))