Bläddra i källkod

Merge branch 'feat/db' of https://github.com/logseq/logseq into feat/db

Konstantinos Kaloutas 1 år sedan
förälder
incheckning
15481d5a7b
29 ändrade filer med 292 tillägg och 112 borttagningar
  1. 9 0
      deps/db/src/logseq/db/frontend/class.cljs
  2. 26 3
      deps/db/src/logseq/db/frontend/property.cljs
  3. 20 2
      deps/db/src/logseq/db/sqlite/create_graph.cljs
  4. 10 0
      deps/db/src/logseq/db/sqlite/util.cljs
  5. 1 1
      deps/outliner/src/logseq/outliner/core.cljs
  6. 97 44
      src/main/frontend/commands.cljs
  7. 1 1
      src/main/frontend/components/block.cljs
  8. 2 2
      src/main/frontend/components/db_based/page.cljs
  9. 2 2
      src/main/frontend/components/editor.cljs
  10. 1 1
      src/main/frontend/components/icon.cljs
  11. 1 4
      src/main/frontend/components/page.cljs
  12. 2 2
      src/main/frontend/components/property.cljs
  13. 5 5
      src/main/frontend/components/property/closed_value.cljs
  14. 2 2
      src/main/frontend/components/property/value.cljs
  15. 1 1
      src/main/frontend/extensions/pdf/assets.cljs
  16. 30 12
      src/main/frontend/handler/db_based/property.cljs
  17. 20 0
      src/main/frontend/handler/db_based/status.cljs
  18. 3 3
      src/main/frontend/handler/editor.cljs
  19. 2 2
      src/main/frontend/handler/file_based/editor.cljs
  20. 1 1
      src/main/frontend/handler/file_based/status.cljs
  21. 1 1
      src/main/frontend/handler/graph.cljs
  22. 27 7
      src/main/frontend/handler/property/util.cljs
  23. 6 6
      src/main/frontend/handler/whiteboard.cljs
  24. 2 2
      src/main/frontend/util/priority.cljs
  25. 3 1
      src/main/frontend/worker/rtc/asset_sync.cljs
  26. 2 2
      src/test/frontend/handler/db_based/property_test.cljs
  27. 3 3
      src/test/frontend/util/marker_test.cljs
  28. 9 1
      src/test/frontend/worker/rtc/asset_sync_effects_test.cljs
  29. 3 1
      src/test/frontend/worker/rtc/mock.cljs

+ 9 - 0
deps/db/src/logseq/db/frontend/class.cljs

@@ -0,0 +1,9 @@
+(ns logseq.db.frontend.class
+  "Class related fns for DB graphs and frontend/datascript usage")
+
+;; TODO: disable name changes for those built-in page/class names and their properties names
+(def ^:large-vars/data-var built-in-classes
+  {:task {:original-name "Task"
+          :schema {:properties ["status" "priority"]}}
+   ;; TODO: Add more classes such as :book, :paper, :movie, :music, :project
+   })

+ 26 - 3
deps/db/src/logseq/db/frontend/property.cljs

@@ -45,7 +45,25 @@
    :logseq.order-list-type {:schema {:type :default}}
    :logseq.tldraw.page {:schema {:type :map}}
    :logseq.tldraw.shape {:schema {:type :map}}
-   ;; TODO: Add enums for logseq.color, logseq.table.headers and logseq.table.hover
+
+   ;; Task props
+   :status {:original-name "Status"
+            :schema
+            {:type :default}
+            :closed-values
+            (mapv #(hash-map :value % :uuid (random-uuid))
+                  ["Backlog" "Todo" "Doing" "In Review" "Done" "Canceled"])
+            :visible true}
+   :priority {:original-name "Priority"
+              :schema
+              {:type :default}
+              :closed-values
+              (mapv #(hash-map :value % :uuid (random-uuid))
+                    ["Urgent" "High" "Medium" "Low"])
+              :visible true}
+
+   ;; TODO: Add more props :Assignee, :Estimate, :Cycle, :Project
+
    ;; color props
    :logseq.color {:schema
                   {:type :default :hide? true}
@@ -117,7 +135,7 @@
           (get coll (:block/uuid property)))
         (get coll key)))))
 
-(defn get-property
+(defn get-block-property-value
   "Get the value of block's property `key`"
   [repo db block key]
   (when db
@@ -132,6 +150,11 @@
     (:block/uuid (d/entity db [:block/name (common-util/page-name-sanity-lc (name property-name))]))
     property-name))
 
+(defn get-property
+  "Get a property given its unsanitized name"
+  [db property-name]
+  (d/entity db [:block/name (common-util/page-name-sanity-lc (name property-name))]))
+
 (defn shape-block?
   [repo db block]
-  (= :whiteboard-shape (get-property repo db block :ls-type)))
+  (= :whiteboard-shape (get-block-property-value repo db block :ls-type)))

+ 20 - 2
deps/db/src/logseq/db/sqlite/create_graph.cljs

@@ -3,6 +3,7 @@
   (:require [logseq.db.sqlite.util :as sqlite-util]
             [logseq.db.frontend.schema :as db-schema]
             [logseq.db.frontend.property :as db-property]
+            [logseq.db.frontend.class :as db-class]
             [logseq.db.frontend.property.util :as db-property-util]
             [logseq.common.util :as common-util]
             [datascript.core :as d]
@@ -39,5 +40,22 @@
                                      :block/name (common-util/page-name-sanity-lc k-name)
                                      :block/uuid (d/squuid)})])))
                             db-property/built-in-properties)
-        ]
-    (concat initial-data initial-files default-pages default-properties)))
+        name->properties (zipmap
+                          (map :block/name default-properties)
+                          default-properties)
+        default-classes (map
+                         (fn [[k-keyword {:keys [schema original-name]}]]
+                           (let [k-name (name k-keyword)]
+                             (sqlite-util/build-new-class
+                              {:block/original-name (or original-name k-name)
+                               :block/name (common-util/page-name-sanity-lc k-name)
+                               :block/uuid (d/squuid)
+                               :block/schema {:properties
+                                              (mapv
+                                               (fn [property-name]
+                                                 (let [id (:block/uuid (get name->properties property-name))]
+                                                   (assert id (str "Built-in property " property-name " is not defined yet"))
+                                                   id))
+                                               (:properties schema))}})))
+                         db-class/built-in-classes)]
+    (concat initial-data initial-files default-pages default-classes default-properties)))

+ 10 - 0
deps/db/src/logseq/db/sqlite/util.cljs

@@ -41,3 +41,13 @@
            :block/journal? false
            :block/format :markdown}
           block)))
+
+
+(defn build-new-class
+  "Build a standard new class so that it is is consistent across contexts"
+  [block]
+  (block-with-timestamps
+   (merge {:block/type "class"
+           :block/journal? false
+           :block/format :markdown}
+          block)))

+ 1 - 1
deps/outliner/src/logseq/outliner/core.cljs

@@ -560,7 +560,7 @@
   (let [db @conn
         tb (when target-block (block db target-block))
         target-block (if sibling? target-block (when tb (:block (otree/-get-down tb conn))))
-        list-type-fn (fn [block] (db-property/get-property repo db block :logseq.order-list-type))
+        list-type-fn (fn [block] (db-property/get-block-property-value repo db block :logseq.order-list-type))
         k (db-property/get-pid repo db :logseq.order-list-type)]
     (if-let [list-type (and target-block (list-type-fn target-block))]
       (mapv

+ 97 - 44
src/main/frontend/commands.cljs

@@ -13,9 +13,9 @@
             [frontend.state :as state]
             [frontend.util :as util]
             [frontend.util.cursor :as cursor]
-            [frontend.util.marker :as marker]
             [frontend.util.priority :as priority]
             [frontend.handler.file-based.property :as file-property-handler]
+            [frontend.handler.property.util :as pu]
             [frontend.handler.property.file :as property-file]
             [goog.dom :as gdom]
             [goog.object :as gobj]
@@ -24,7 +24,10 @@
             [logseq.common.util :as common-util]
             [logseq.common.util.block-ref :as block-ref]
             [logseq.common.util.page-ref :as page-ref]
-            [promesa.core :as p]))
+            [promesa.core :as p]
+            [frontend.handler.file-based.status :as file-based-status]
+            [frontend.handler.db-based.status :as db-based-status]
+            [frontend.handler.db-based.property :as db-property-handler]))
 
 ;; TODO: move to frontend.handler.editor.commands
 
@@ -85,7 +88,7 @@
 (defn ->marker
   [marker]
   [[:editor/clear-current-slash]
-   [:editor/set-marker marker]
+   [:editor/set-status marker]
    [:editor/move-cursor-to-end]])
 
 (defn ->priority
@@ -113,6 +116,18 @@
                                     :backward-pos 4}]
    [:editor/search-block :embed]])
 
+(defn file-based-statuses
+  []
+  (let [workflow (state/get-preferred-workflow)]
+    (if (= :now workflow)
+      ["LATER" "NOW" "TODO" "DOING" "DONE" "WAITING" "CANCELED"]
+      ["TODO" "DOING" "LATER" "NOW" "DONE" "WAITING" "CANCELED"])))
+
+(defn db-based-statuses
+  []
+  (map (fn [id] (get-in (db/entity [:block/uuid id]) [:block/schema :value]))
+    (pu/get-closed-property-values "status")))
+
 (defn db-based-embed-page
   []
   [[:editor/input "[[]]" {:last-pattern command-trigger
@@ -125,18 +140,34 @@
                           :backward-pos 2}]
    [:editor/search-block :embed]])
 
-(defn get-preferred-workflow
+(defn get-statuses
   []
-  (let [workflow (state/get-preferred-workflow)]
-    (if (= :now workflow)
-      [["LATER" (->marker "LATER")]
-       ["NOW" (->marker "NOW")]
-       ["TODO" (->marker "TODO")]
-       ["DOING" (->marker "DOING")]]
-      [["TODO" (->marker "TODO")]
-       ["DOING" (->marker "DOING")]
-       ["LATER" (->marker "LATER")]
-       ["NOW" (->marker "NOW")]])))
+  (let [result (->>
+                (if (config/db-based-graph? (state/get-current-repo))
+                  (db-based-statuses)
+                  (file-based-statuses))
+                (mapv (fn [m] [m (->marker m) (str "Set status to " m)])))]
+    (when (seq result)
+      (update result 0 (fn [v] (conj v "TASK"))))))
+
+(defn file-based-priorities
+  []
+  ["A" "B" "C"])
+
+(defn db-based-priorities
+  []
+  (map (fn [id] (get-in (db/entity [:block/uuid id]) [:block/schema :value]))
+    (pu/get-closed-property-values "priority")))
+
+(defn get-priorities
+  []
+  (let [result (->>
+                (if (config/db-based-graph? (state/get-current-repo))
+                  (db-based-priorities)
+                  (file-based-priorities))
+                (mapv (fn [item] [item (->priority item) (str "Set priority to " item)])))]
+    (when (seq result)
+      (update result 0 (fn [v] (conj v "PRIORITY"))))))
 
 ;; Credits to roamresearch.com
 
@@ -155,15 +186,6 @@
 (defonce *matched-commands (atom nil))
 (defonce *initial-commands (atom nil))
 
-(defonce *first-command-group
-  {"Page reference" "BASIC"
-   "Tomorrow" "TIME & DATE"
-   "LATER" "TASK"
-   "A" "PRIORITY"
-   "Number list" "LIST TYPE"
-   "Query" "ADVANCED"
-   "Quote" "ORG-MODE"})
-
 (defn ->block
   ([type]
    (->block type nil))
@@ -202,7 +224,9 @@
   []
   (->>
    (concat
-    [["Quote" (->block "quote")]
+    [["Quote" (->block "quote")
+      "Add a quote"
+      "More"]
      ["Src" (->block "src" "")]
      ["Query" (->block "query")]
      ["Latex export" (->block "export" "latex")]
@@ -235,8 +259,11 @@
     (->>
      (concat
     ;; basic
-      [["Page reference" [[:editor/input page-ref/left-and-right-brackets {:backward-pos 2}]
-                          [:editor/search-page]] "Create a backlink to a page"]
+      [["Page reference"
+        [[:editor/input page-ref/left-and-right-brackets {:backward-pos 2}]
+         [:editor/search-page]]
+        "Create a backlink to a page"
+        "BASIC"]
        ["Page embed" (embed-page) "Embed a page here"]
        ["Block reference" [[:editor/input block-ref/left-and-right-parens {:backward-pos 2}]
                            [:editor/search-block :reference]] "Create a backlink to a block"]
@@ -261,37 +288,41 @@
 
     ;; time & date
 
-      [["Tomorrow" #(get-page-ref-text (date/tomorrow)) "Insert the date of tomorrow"]
+      [["Tomorrow"
+        #(get-page-ref-text (date/tomorrow))
+        "Insert the date of tomorrow"
+        "TIME & DATE"]
        ["Yesterday" #(get-page-ref-text (date/yesterday)) "Insert the date of yesterday"]
        ["Today" #(get-page-ref-text (date/today)) "Insert the date of today"]
        ["Current time" #(date/get-current-time) "Insert current time"]
        ["Date picker" [[:editor/show-date-picker]] "Pick a date and insert here"]]
 
-    ;; order list
-      [["Number list" [[:editor/clear-current-slash]
-                       [:editor/toggle-own-number-list]] "Number list"]
+      ;; order list
+      [["Number list"
+        [[:editor/clear-current-slash]
+         [:editor/toggle-own-number-list]]
+        "Number list"
+        "LIST TYPE"]
        ["Number children" [[:editor/clear-current-slash]
                            [:editor/toggle-children-number-list]] "Number children"]]
 
     ;; task management
-      (get-preferred-workflow)
-      [["DONE" (->marker "DONE")]
-       ["WAITING" (->marker "WAITING")]
-       ["CANCELED" (->marker "CANCELED")]
-       ["Deadline" [[:editor/clear-current-slash]
+      (get-statuses)
+      [["Deadline" [[:editor/clear-current-slash]
                     [:editor/show-date-picker :deadline]]]
        ["Scheduled" [[:editor/clear-current-slash]
                      [:editor/show-date-picker :scheduled]]]]
 
     ;; priority
-      [["A" (->priority "A")]
-       ["B" (->priority "B")]
-       ["C" (->priority "C")]]
+      (get-priorities)
 
     ;; advanced
 
-      [["Query" [[:editor/input "{{query }}" {:backward-pos 2}]
-                 [:editor/exit]] query-doc]
+      [["Query"
+        [[:editor/input "{{query }}" {:backward-pos 2}]
+         [:editor/exit]]
+        query-doc
+        "ADVANCED"]
        ["Zotero" (zotero-steps) "Import Zotero journal article"]
        ["Query function" [[:editor/input "{{function }}" {:backward-pos 2}]] "Create a query function"]
        ["Calculator" [[:editor/input "```calc\n\n```" {:type "block"
@@ -579,7 +610,7 @@
 
 (defn compute-pos-delta-when-change-marker
   [edit-content marker pos]
-  (let [old-marker (some->> (first (util/safe-re-find marker/bare-marker-pattern edit-content))
+  (let [old-marker (some->> (first (util/safe-re-find file-based-status/bare-marker-pattern edit-content))
                             (string/trim))
         pos-delta (- (count marker)
                      (count old-marker))
@@ -592,7 +623,8 @@
                         pos-delta)]
     (max (+ pos pos-delta) 0)))
 
-(defmethod handle-step :editor/set-marker [[_ marker] format]
+(defn- file-based-set-status
+  [marker format]
   (when-let [input-id (state/get-edit-input-id)]
     (when-let [current-input (gdom/getElement input-id)]
       (let [edit-content (gobj/get current-input "value")
@@ -607,7 +639,7 @@
                     (count (util/safe-re-find re-pattern prefix))))
             new-value (str (subs edit-content 0 pos)
                            (string/replace-first (subs edit-content pos)
-                                                 (marker/marker-pattern format)
+                                                 (file-based-status/marker-pattern format)
                                                  (str marker " ")))]
         (state/set-edit-content! input-id new-value)
         (let [new-pos (compute-pos-delta-when-change-marker
@@ -615,7 +647,18 @@
           ;; TODO: any performance issue?
           (js/setTimeout #(cursor/move-cursor-to current-input new-pos) 10))))))
 
-(defmethod handle-step :editor/set-priority [[_ priority] _format]
+(defn- db-based-set-status
+  [status]
+  (when-let [block (state/get-edit-block)]
+    (db-property-handler/batch-set-property-closed-value! [(:block/uuid block)] "status" status)))
+
+(defmethod handle-step :editor/set-status [[_ status] format]
+  (if (config/db-based-graph? (state/get-current-repo))
+    (db-based-set-status status)
+    (file-based-set-status status format)))
+
+(defn- file-based-set-priority
+  [priority]
   (when-let [input-id (state/get-edit-input-id)]
     (when-let [current-input (gdom/getElement input-id)]
       (let [format (or (db/get-page-format (state/get-current-page)) (state/get-preferred-format))
@@ -624,6 +667,16 @@
             new-value (string/trim (priority/add-or-update-priority edit-content format new-priority))]
         (state/set-edit-content! input-id new-value)))))
 
+(defn- db-based-set-priority
+  [priority]
+  (when-let [block (state/get-edit-block)]
+    (db-property-handler/batch-set-property-closed-value! [(:block/uuid block)] "priority" priority)))
+
+(defmethod handle-step :editor/set-priority [[_ priority] _format]
+  (if (config/db-based-graph? (state/get-current-repo))
+    (db-based-set-priority priority)
+    (file-based-set-priority priority)))
+
 (defmethod handle-step :editor/insert-properties [[_ _] _format]
   (when-let [input-id (state/get-edit-input-id)]
     (when-let [current-input (gdom/getElement input-id)]

+ 1 - 1
src/main/frontend/components/block.cljs

@@ -582,7 +582,7 @@
       :on-key-up (fn [e] (when (and e (= (.-key e) "Enter"))
                            (open-page-ref e config page-name redirect-page-name page-name-in-block contents-page? whiteboard-page?)))}
      (when-not hide-icon?
-       (when-let [icon (pu/get-property page-entity :icon)]
+       (when-let [icon (pu/get-block-property-value page-entity :icon)]
          [:span.mr-1 (icon/icon icon)]))
      (if (and (coll? children) (seq children))
        (for [child children]

+ 2 - 2
src/main/frontend/components/db_based/page.cljs

@@ -90,7 +90,7 @@
   [page]
   [:div.grid.grid-cols-5.gap-1.items-center.leading-8
    [:label.col-span-2 "Icon:"]
-   (let [icon-value (pu/get-property page :icon)]
+   (let [icon-value (pu/get-block-property-value page :icon)]
      [:div.col-span-3.flex.flex-row.items-center.gap-2
       (icon-component/icon-picker icon-value
                                   {:disabled? config/publishing?
@@ -216,4 +216,4 @@
       :on-toggle (fn [value]
                    (when (false? value)
                      (reset! *configuring? false)
-                     (reset! *hover? false)))})))
+                     (reset! *hover? false)))})))

+ 2 - 2
src/main/frontend/components/editor.cljs

@@ -1,7 +1,7 @@
 (ns frontend.components.editor
   (:require [clojure.string :as string]
             [frontend.commands :as commands
-             :refer [*first-command-group *matched-block-commands *matched-commands]]
+             :refer [*matched-block-commands *matched-commands]]
             [frontend.components.datetime :as datetime-comp]
             [frontend.components.svg :as svg]
             [frontend.components.search :as search]
@@ -40,7 +40,7 @@
        matched
        {:get-group-name
         (fn [item]
-          (get *first-command-group (first item)))
+          (when (= (count item) 4) (last item)))
 
         :item-render
         (fn [item]

+ 1 - 1
src/main/frontend/components/icon.cljs

@@ -27,7 +27,7 @@
 (defn get-page-icon
   [page-entity opts]
   (let [default-icon (ui/icon "page" (merge opts {:extension? true}))
-        page-icon (pu/get-property page-entity :icon)]
+        page-icon (pu/get-block-property-value page-entity :icon)]
     (or
      (when-not (string/blank? page-icon)
        (icon page-icon opts))

+ 1 - 4
src/main/frontend/components/page.cljs

@@ -482,8 +482,6 @@
           block? (some? (:block/page page))
           journal? (db/journal-page? page-name)
           db-based? (config/db-based-graph? repo)
-          built-in-property? (and (contains? (:block/type page) "property")
-                                  (contains? db-property/built-in-properties-keys-str page-name))
           fmt-journal? (boolean (date/journal-title->int page-name))
           whiteboard? (:whiteboard? option) ;; in a whiteboard portal shape?
           whiteboard-page? (model/whiteboard-page? page-name) ;; is this page a whiteboard?
@@ -526,7 +524,6 @@
                  (when (and (not whiteboard?) original-name)
                    (page-title page-name {:journal? journal?
                                           :fmt-journal? fmt-journal?
-                                          :built-in-property? built-in-property?
                                           :preview? preview?})))
                (when (not config/publishing?)
                  (when config/lsp-enabled?
@@ -1241,7 +1238,7 @@
                               {:on-change (fn []
                                             (swap! *checks update idx not))})]
                [:td.icon.w-4.p-0.overflow-hidden
-                (when-let [icon (pu/get-property page :icon)]
+                (when-let [icon (pu/get-block-property-value page :icon)]
                   icon)]
                [:td.name [:a {:on-click (fn [e]
                                           (.preventDefault e)

+ 2 - 2
src/main/frontend/components/property.cljs

@@ -160,7 +160,7 @@
 
       [:div.grid.grid-cols-4.gap-1.items-center.leading-8
        [:label.col-span-1 "Icon:"]
-       (let [icon-value (pu/get-property property :icon)]
+       (let [icon-value (pu/get-block-property-value property :icon)]
          [:div.col-span-3.flex.flex-row.items-center.gap-2
           (icon-component/icon-picker icon-value
                                       {:disabled? disabled?
@@ -507,7 +507,7 @@
   [state block property {:keys [class-schema? block? collapsed? page-cp inline-text]}]
   (let [*hover? (::hover? state)
         repo (state/get-current-repo)
-        icon (pu/get-property property :icon)]
+        icon (pu/get-block-property-value property :icon)]
     [:div.flex.flex-row.items-center {:on-mouse-over #(reset! *hover? true)
                                       :on-mouse-leave #(reset! *hover? false)}
      (when block?

+ 5 - 5
src/main/frontend/components/property/closed_value.cljs

@@ -44,7 +44,7 @@
   {:init (fn [state]
            (let [block (second (:rum/args state))
                  value (or (str (get-in block [:block/schema :value])) "")
-                 icon (when block (pu/get-property block :icon))
+                 icon (when block (pu/get-block-property-value block :icon))
                  description (or (get-in block [:block/schema :description]) "")]
              (assoc state
                     ::value (atom value)
@@ -107,7 +107,7 @@
      {:on-mouse-over #(reset! *hover? true)
       :on-mouse-out #(reset! *hover? false)}
      [:div.flex.flex-row.items-center.gap-2
-      (icon-component/icon-picker (pu/get-property item :icon)
+      (icon-component/icon-picker (pu/get-block-property-value item :icon)
                                   {:on-chosen (fn [_e icon]
                                                 (update-icon icon))})
       (if (and page? (:page-cp parent-opts))
@@ -144,9 +144,9 @@
           (assoc opts :on-save
                  (fn [value icon description]
                    (<upsert-closed-value! property {:id uuid
-                                                   :value value
-                                                   :description description
-                                                   :icon icon}))))))
+                                                    :value value
+                                                    :description description
+                                                    :icon icon}))))))
      dropdown-opts)))
 
 (rum/defc add-existing-values

+ 2 - 2
src/main/frontend/components/property/value.cljs

@@ -369,7 +369,7 @@
         items (if closed-values?
                 (keep (fn [id]
                         (when-let [block (when id (db/entity [:block/uuid id]))]
-                          (let [icon (pu/get-property block :icon)
+                          (let [icon (pu/get-block-property-value block :icon)
                                 value (or (:block/original-name block)
                                           (get-in block [:block/schema :value]))]
                             {:label (if icon
@@ -495,7 +495,7 @@
       [:div.text-sm.opacity-70 "loading"]
       (when-let [block (db/sub-block (:db/id (db/entity [:block/uuid value])))]
         (let [value' (get-in block [:block/schema :value])
-              icon (pu/get-property block :icon)]
+              icon (pu/get-block-property-value block :icon)]
           (cond
             (:block/name block)
             (page-cp {:disable-preview? true

+ 1 - 1
src/main/frontend/extensions/pdf/assets.cljs

@@ -237,7 +237,7 @@
         page-name (:block/original-name page)
         ;; FIXME: file-path property for db version
         file-path (:file-path (:block/properties page))
-        hl-page   (pu/get-property block :hl-page)]
+        hl-page   (pu/get-block-property-value block :hl-page)]
     (when-let [target-key (and page-name (subs page-name 5))]
       (p/let [hls (resolve-hls-data-by-key$ target-key)
               hls (and hls (:highlights hls))]

+ 30 - 12
src/main/frontend/handler/db_based/property.cljs

@@ -16,7 +16,9 @@
             [malli.util :as mu]
             [malli.error :as me]
             [logseq.common.util.page-ref :as page-ref]
-            [datascript.impl.entity :as e]))
+            [datascript.impl.entity :as e]
+            [logseq.db.frontend.property :as db-property]
+            [frontend.handler.property.util :as pu]))
 
 ;; schema -> type, cardinality, object's class
 ;;           min, max -> string length, number range, cardinality size limit
@@ -233,7 +235,8 @@
                   (do
                     (upsert-property! repo k-name (assoc property-schema :type property-type)
                                       {:property-uuid property-uuid})
-                    (let [new-value (cond
+                    (let [status? (= "status" (string/lower-case k-name))
+                          new-value (cond
                                       (and multiple-values? old-value
                                            (not= old-value :frontend.components.property/new-value-placeholder))
                                       (if (coll? v*)
@@ -256,15 +259,16 @@
                                         (set (remove string/blank? new-value)))
                                       new-value)
                           block-properties (assoc properties property-uuid new-value)
-                          refs (rebuild-block-refs repo
-                                                                 block
-                                                                 block-properties)]
-                      (db/transact! repo
-                                    [[:db/retract (:db/id block) :block/refs]
-                                     {:block/uuid (:block/uuid block)
-                                      :block/properties block-properties
-                                      :block/refs refs}]
-                                    {:outliner-op :save-block}))))))))))))
+                          refs (rebuild-block-refs repo block block-properties)
+                          tx-data [[:db/retract (:db/id block) :block/refs]
+                                   {:block/uuid (:block/uuid block)
+                                    :block/properties block-properties
+                                    :block/refs refs}
+                                   ;; Add task tag
+                                   (when status?
+                                     (when-let [task-id (:db/id (db-property/get-property (db/get-db repo) "task"))]
+                                       [:db/add (:db/id block) :block/tags task-id]))]]
+                      (db/transact! repo tx-data {:outliner-op :save-block}))))))))))))
 
 (defn- fix-cardinality-many-values!
   [repo property-uuid]
@@ -372,6 +376,7 @@
             (upsert-property! repo k-name (assoc (:block/schema property) :type property-type)
                               {:property-uuid property-uuid}))
         {:keys [cardinality]} (:block/schema property)
+        status? (= "status" (string/lower-case k-name))
         txs (mapcat
              (fn [id]
                (when-let [block (db/entity [:block/uuid id])]
@@ -387,7 +392,10 @@
                      [[:db/retract (:db/id block) :block/refs]
                       {:block/uuid (:block/uuid block)
                        :block/properties block-properties
-                       :block/refs refs}]))))
+                       :block/refs refs}
+                      (when status?
+                        (when-let [task-id (:db/id (db-property/get-property (db/get-db repo) "task"))]
+                          [:db/add (:db/id block) :block/tags task-id]))]))))
              block-ids)]
     (when (seq txs)
       (db/transact! repo txs {:outliner-op :save-block}))))
@@ -799,3 +807,13 @@
         from-property (when created-from-property (db/entity [:block/uuid created-from-property]))]
     {:from-block-id (or (:db/id from-block) (:db/id b))
      :from-property-id (:db/id from-property)}))
+
+(defn batch-set-property-closed-value!
+  [block-ids property-name closed-value]
+  (let [repo (state/get-current-repo)
+        closed-value-id (:block/uuid (pu/get-closed-value-entity-by-name property-name closed-value))]
+    (when closed-value-id
+      (batch-set-property! repo
+                           block-ids
+                           property-name
+                           closed-value-id))))

+ 20 - 0
src/main/frontend/handler/db_based/status.cljs

@@ -0,0 +1,20 @@
+(ns frontend.handler.db-based.status
+  "Task status related util fns"
+  (:require [frontend.handler.db-based.property :as db-property-handler]
+            [frontend.handler.property.util :as pu]
+            [frontend.state :as state]))
+
+(defn set-status!
+  [block status-value-name]
+  (let [repo (state/get-current-repo)
+        status-id (:block/uuid (pu/get-closed-value-entity-by-name "status" status-value-name))]
+    (when status-id
+      (db-property-handler/set-block-property! repo
+                                               (:block/uuid block)
+                                               "status"
+                                               status-id
+                                               {}))))
+
+(defn cycle-status!
+  [block status]
+  )

+ 3 - 3
src/main/frontend/handler/editor.cljs

@@ -44,7 +44,7 @@
             [frontend.util.drawer :as drawer]
             [frontend.util.keycode :as keycode]
             [frontend.util.list :as list]
-            [frontend.util.marker :as marker]
+            [frontend.handler.file-based.status :as status]
             [frontend.handler.property.file :as property-file]
             [frontend.util.text :as text-util]
             [frontend.util.thingatpt :as thingatpt]
@@ -635,7 +635,7 @@
   ([block]
    (set-marker block nil))
   ([{:block/keys [marker content format] :as block} new-marker]
-   (let [[new-content _] (marker/cycle-marker content marker new-marker format (state/get-preferred-workflow))]
+   (let [[new-content _] (status/cycle-marker content marker new-marker format (state/get-preferred-workflow))]
      (save-block-if-changed! block new-content))))
 
 (defn cycle-todos!
@@ -663,7 +663,7 @@
               content (state/get-edit-content)
               format (or (db/get-page-format (state/get-current-page))
                          (state/get-preferred-format))
-              [new-content marker] (marker/cycle-marker content nil nil format (state/get-preferred-workflow))
+              [new-content marker] (status/cycle-marker content nil nil format (state/get-preferred-workflow))
               new-pos (commands/compute-pos-delta-when-change-marker
                        content marker (cursor/pos current-input))]
           (state/set-edit-content! edit-input-id new-content)

+ 2 - 2
src/main/frontend/handler/file_based/editor.cljs

@@ -12,7 +12,7 @@
             [frontend.util :as util]
             [frontend.util.clock :as clock]
             [frontend.util.drawer :as drawer]
-            [frontend.util.marker :as marker]
+            [frontend.handler.file-based.status :as status]
             [frontend.handler.property.file :as property-file]
             [frontend.handler.file-based.property :as file-property-handler]
             [frontend.handler.file-based.property.util :as property-util]
@@ -62,7 +62,7 @@
   (if (and (state/enable-timetracking?)
            (not= (:block/content block) value))
     (let [format (:block/format block)
-          new-marker (last (util/safe-re-find (marker/marker-pattern format) (or value "")))
+          new-marker (last (util/safe-re-find (status/marker-pattern format) (or value "")))
           new-value (with-marker-time value block format
                       new-marker
                       (:block/marker block))]

+ 1 - 1
src/main/frontend/util/marker.cljs → src/main/frontend/handler/file_based/status.cljs

@@ -1,4 +1,4 @@
-(ns frontend.util.marker
+(ns frontend.handler.file-based.status
   "Task (formerly todo) related util fns"
   (:require [clojure.string :as string]
             [frontend.util :as util]))

+ 1 - 1
src/main/frontend/handler/graph.cljs

@@ -107,7 +107,7 @@
               (not journal?)
               (remove :block/journal?)
               (not excluded-pages?)
-              (remove (fn [p] (true? (pu/get-property p :exclude-from-graph-view)))))
+              (remove (fn [p] (true? (pu/get-block-property-value p :exclude-from-graph-view)))))
             links (concat (seq relation)
                           (seq tagged-pages)
                           (seq namespaces))

+ 27 - 7
src/main/frontend/handler/property/util.cljs

@@ -14,19 +14,26 @@
         db (db/get-db repo)]
     (db-property/lookup repo db coll key)))
 
-(defn get-property
+(defn get-block-property-value
   "Get the value of block's property `key`"
   [block key]
   (let [repo (state/get-current-repo)
         db (db/get-db repo)]
-    (db-property/get-property repo db block key)))
+    (db-property/get-block-property-value repo db block key)))
+
+(defn get-property
+  "Get a property given its unsanitized name"
+  [property-name]
+  (let [repo (state/get-current-repo)
+        db (db/get-db repo)]
+    (db-property/get-property db property-name)))
 
+;; TODO: move this to another ns
 (defn get-page-uuid
   "Get a user property's uuid given its unsanitized name"
   ;; Get a page's uuid given its unsanitized name
-  ([property-name] (get-page-uuid (state/get-current-repo) property-name))
-  ([repo property-name]
-   (:block/uuid (db/entity repo [:block/name (common-util/page-name-sanity-lc (name property-name))]))))
+  [property-name]
+  (:block/uuid (get-property property-name)))
 
 (defn get-pid
   "Get a property's id (name or uuid) given its name. For file and db graphs"
@@ -36,13 +43,26 @@
     (db-property/get-pid repo db property-name)))
 
 (defn block->shape [block]
-  (get-property block :logseq.tldraw.shape))
+  (get-block-property-value block :logseq.tldraw.shape))
 
 (defn page-block->tldr-page [block]
-  (get-property block :logseq.tldraw.page))
+  (get-block-property-value block :logseq.tldraw.page))
 
 (defn shape-block?
   [block]
   (let [repo (state/get-current-repo)
         db (db/get-db repo)]
     (db-property/shape-block? repo db block)))
+
+(defn get-closed-property-values
+  [property-name]
+  (when-let [property (get-property property-name)]
+    (get-in property [:block/schema :values])))
+
+(defn get-closed-value-entity-by-name
+  [property-name value-name]
+  (let [values (get-closed-property-values property-name)]
+    (some (fn [id]
+            (let [e (db/entity [:block/uuid id])]
+              (when (= (get-in e [:block/schema :value]) value-name)
+                e))) values)))

+ 6 - 6
src/main/frontend/handler/whiteboard.cljs

@@ -32,7 +32,7 @@
 
 (defn- build-shapes
   [page-block blocks]
-  (let [page-metadata (pu/get-property page-block :logseq.tldraw.page)
+  (let [page-metadata (pu/get-block-property-value page-block :logseq.tldraw.page)
         shapes-index (:shapes-index page-metadata)
         shape-id->index (zipmap shapes-index (range 0 (count shapes-index)))]
     (->> blocks
@@ -99,17 +99,17 @@
         repo (state/get-current-repo)
         deleted-shapes (when (seq deleted-ids)
                          (->> (db/pull-many repo '[*] (mapv (fn [id] [:block/uuid (uuid id)]) deleted-ids))
-                              (mapv (fn [b] (pu/get-property b :logseq.tldraw.shape)))
+                              (mapv (fn [b] (pu/get-block-property-value b :logseq.tldraw.shape)))
                               (remove nil?)))
         deleted-shapes-tx (mapv (fn [id] [:db/retractEntity [:block/uuid (uuid id)]]) deleted-ids)
         upserted-blocks (->> (map #(shape->block % page-name) upsert-shapes)
                              (remove (fn [b]
                                        (= (:nonce
-                                           (pu/get-property
+                                           (pu/get-block-property-value
                                             (db/entity [:block/uuid (:block/uuid b)])
                                             :logseq.tldraw.shape))
                                           (:nonce
-                                           (pu/get-property
+                                           (pu/get-block-property-value
                                             b
                                             :logseq.tldraw.shape))))))
         page-entity (model/get-page page-name)
@@ -134,7 +134,7 @@
   (let [tl-page ^js (second (first (.-pages app)))
         shapes (.-shapes ^js tl-page)
         page-block (model/get-page page-name)
-        prev-page-metadata (pu/get-property page-block :logseq.tldraw.page)
+        prev-page-metadata (pu/get-block-property-value page-block :logseq.tldraw.page)
         prev-shapes-index (:shapes-index prev-page-metadata)
         shape-id->prev-index (zipmap prev-shapes-index (range (count prev-shapes-index)))
         new-id-nonces (set (map-indexed (fn [idx shape]
@@ -344,7 +344,7 @@
     (let [tl-page ^js (second (first (.-pages app)))]
       (when tl-page
         (when-let [page (db/entity [:block/name page-name])]
-         (let [page-metadata (pu/get-property page :logseq.tldraw.page)
+         (let [page-metadata (pu/get-block-property-value page :logseq.tldraw.page)
                shapes-index (:shapes-index page-metadata)]
            (when (seq shapes-index)
              (.updateShapesIndex tl-page (bean/->js shapes-index)))))))))

+ 2 - 2
src/main/frontend/util/priority.cljs

@@ -2,7 +2,7 @@
   "Util fns for task priorities e.g. A, B, C"
   (:require [clojure.string :as string]
             [frontend.util :as util]
-            [frontend.util.marker :as marker]))
+            [frontend.handler.file-based.status :as status]))
 
 (defn add-or-update-priority
   [content format priority]
@@ -17,7 +17,7 @@
             (+ start-pos (count content)))
           (count (util/safe-re-find re-pattern content)))
         skip-marker-pos
-        (if-let [matches (seq (util/re-pos marker/bare-marker-pattern (subs content skip-hash-pos)))]
+        (if-let [matches (seq (util/re-pos status/bare-marker-pattern (subs content skip-hash-pos)))]
           (let [[start-pos content] (last matches)]
             (+ start-pos (count content)))
           0)

+ 3 - 1
src/main/frontend/worker/rtc/asset_sync.cljs

@@ -124,7 +124,9 @@
           stop-assets-sync-loop-chan (chan)]
       (reset! (:*stop-asset-sync-loop-chan state) stop-assets-sync-loop-chan)
       (async/sub data-from-ws-pub "push-assets-updates" push-data-from-ws-ch)
-      (when loop-started-ch (async/close! loop-started-ch))
+      (when loop-started-ch
+        (prn ::just-for-test (<? (ws/<send&receive state {:action "list-graphs"})))
+        (async/close! loop-started-ch))
       (<! (go-loop [push-assets-update-ops-ch
                     (make-push-assets-update-ops-timeout-ch repo (not @*auto-push-assets-update-ops?))]
             (let [{:keys [continue push-data-from-ws client-assets-update stop]}

+ 2 - 2
src/test/frontend/handler/db_based/property_test.cljs

@@ -153,9 +153,9 @@
       (let [fb (db/entity [:block/uuid fbid])
             sb (db/entity [:block/uuid sbid])]
         (are [x y] (= x y)
-          (pu/get-property fb k)
+          (pu/get-block-property-value fb k)
           v
-          (pu/get-property sb k)
+          (pu/get-block-property-value sb k)
           v))))
 
   (testing "Batch remove properties"

+ 3 - 3
src/test/frontend/util/marker_test.cljs

@@ -1,9 +1,9 @@
 (ns frontend.util.marker-test
   (:require [cljs.test :refer [are deftest]]
-            [frontend.util.marker :as marker]))
+            [frontend.handler.file-based.status :as status]))
 
 (deftest add-or-update-marker-markdown
-  (are [content marker expect] (= expect (marker/add-or-update-marker content :markdown marker))
+  (are [content marker expect] (= expect (status/add-or-update-marker content :markdown marker))
     "test content" "TODO" "TODO test content"
     "\nxxx\n" "TODO" "TODO xxx\n"
     "## xxx" "TODO" "## TODO xxx"
@@ -17,7 +17,7 @@
     "TODO #test content" "DONE" "DONE #test content"))
 
 (deftest add-or-update-marker-org
-  (are [content marker expect] (= expect (marker/add-or-update-marker content :org marker))
+  (are [content marker expect] (= expect (status/add-or-update-marker content :org marker))
     "test content" "TODO" "TODO test content"
     "\nxxx\n" "TODO" "TODO xxx\n"
     "" "TODO" "TODO "

+ 9 - 1
src/test/frontend/worker/rtc/asset_sync_effects_test.cljs

@@ -4,10 +4,18 @@
   (:require [cljs.core.async :as async :refer [<! >! go timeout]]
             [clojure.test :as t :refer [deftest is use-fixtures]]
             [frontend.test.helper :include-macros true :as test-helper]
-            [frontend.worker.rtc.fixture :as rtc-fixture]))
+            [frontend.worker.rtc.fixture :as rtc-fixture]
+            [spy.core :as spy]))
 
 (use-fixtures :each
   test-helper/start-and-destroy-db-map-fixture
   rtc-fixture/listen-test-db-fixture
   rtc-fixture/start-and-stop-asset-sync-loop-fixture
   rtc-fixture/clear-op-mem-stores-fixture)
+
+
+(deftest asset-sync-loop-init-test
+  (let [ws @(:*ws @rtc-fixture/*test-asset-sync-state)
+        handler-fn (:handler-fn ws)
+        ws-msg (first (spy/last-call handler-fn))]
+    (is (= "list-graphs" (:action ws-msg)))))

+ 3 - 1
src/test/frontend/worker/rtc/mock.cljs

@@ -24,8 +24,10 @@
   (case (:action msg)
     "register-graph-updates"
     (async/offer! push-data-to-client-chan (select-keys msg [:req-id]))
+    "list-graphs"
+    (async/offer! push-data-to-client-chan (assoc (select-keys msg [:req-id])
+                                                  :graphs []))
     ;; default
-
     nil))