Browse Source

wip: schema migration

Tienson Qin 11 months ago
parent
commit
c428b87dce

+ 1 - 1
deps/db/src/logseq/db.cljs

@@ -182,7 +182,7 @@
     (if (db-based-graph? db)
       ;; Classes and properties are case sensitive
       (let [tags (if (coll? tags) (set tags) #{tags})]
-        (if (set/intersection #{:logseq.class/Class :logseq.class/Property} tags)
+        (if (set/intersection #{:logseq.class/Tag :logseq.class/Property} tags)
           (seq
            (d/q
             '[:find [?p ...]

+ 15 - 4
deps/db/src/logseq/db/frontend/class.cljs

@@ -10,9 +10,19 @@
    :logseq.class/Root {:title "Root Tag"}
 
    :logseq.class/Page {:title "Page"}
-   :logseq.class/Whiteboard {:title "Whiteboard"}
-   :logseq.class/Class {:title "Tag"}
-   :logseq.class/Property {:title "Property"}
+
+   :logseq.class/Tag
+   {:title "Tag"
+    :properties {:block/tags :logseq.class/Page}}
+
+   :logseq.class/Whiteboard
+   {:title "Whiteboard"
+    :properties {:block/tags :logseq.class/Page}}
+
+   :logseq.class/Property
+   {:title "Property"
+    :properties {:block/tags :logseq.class/Page}}
+
    :logseq.class/Closed-Value {:title "Closed Value"}
 
    :logseq.class/Task
@@ -21,7 +31,8 @@
 
    :logseq.class/Journal
    {:title "Journal"
-    :properties {:logseq.property.journal/title-format "MMM do, yyyy"}}
+    :properties {:block/tags :logseq.class/Page
+                 :logseq.property.journal/title-format "MMM do, yyyy"}}
 
    :logseq.class/Query
    {:title "Query"

+ 1 - 1
deps/db/src/logseq/db/frontend/entity_util.cljs

@@ -23,7 +23,7 @@
 
 (defn class?
   [entity]
-  (has-tag? entity :logseq.class/Class))
+  (has-tag? entity :logseq.class/Tag))
 
 (defn property?
   [entity]

+ 1 - 1
deps/db/src/logseq/db/frontend/schema.cljs

@@ -2,7 +2,7 @@
   "Main datascript schemas for the Logseq app"
   (:require [clojure.set :as set]))
 
-(def version 49)
+(def version 51)
 
 ;; A page is a special block, a page can corresponds to multiple files with the same ":block/name".
 (def ^:large-vars/data-var schema

+ 1 - 1
deps/db/src/logseq/db/sqlite/util.cljs

@@ -115,7 +115,7 @@
   {:pre [(qualified-keyword? (:db/ident block))]}
   (block-with-timestamps
    (cond-> (merge block
-                  {:block/tags #{:logseq.class/Class}
+                  {:block/tags #{:logseq.class/Tag}
                    :block/format :markdown})
      (and (not= (:db/ident block) :logseq.class/Root)
           (nil? (:logseq.property/parent block)))

+ 1 - 1
deps/graph-parser/src/logseq/graph_parser/block.cljs

@@ -390,7 +390,7 @@
                                   [page nil]))]
       (when page
         (if (ldb/db-based-graph? db)
-          (let [tags (if class? [:logseq.class/Class]
+          (let [tags (if class? [:logseq.class/Tag]
                          (or (:block/tags page)
                              [:logseq.class/Page]))]
             (assoc page :block/tags tags))

+ 7 - 7
deps/graph-parser/src/logseq/graph_parser/exporter.cljs

@@ -113,7 +113,7 @@
   (if block-ns
     (->> (d/q '[:find [?b ...]
                 :in $ ?name
-                :where [?b :block/uuid ?uuid] [?b :block/tags :logseq.class/Class] [?b :block/name ?name]]
+                :where [?b :block/uuid ?uuid] [?b :block/tags :logseq.class/Tag] [?b :block/name ?name]]
               db
               (ns-util/get-last-part full-name))
          (map #(d/entity db %))
@@ -125,7 +125,7 @@
     (first
      (d/q '[:find [?uuid ...]
             :in $ ?name
-            :where [?b :block/uuid ?uuid] [?b :block/tags :logseq.class/Class] [?b :block/name ?name]]
+            :where [?b :block/uuid ?uuid] [?b :block/tags :logseq.class/Tag] [?b :block/name ?name]]
           db
           full-name))))
 
@@ -989,7 +989,7 @@
                                                          (all-existing-page-uuids (::original-name m))
                                                          (all-existing-page-uuids (:block/name m)))]
                                       (build-existing-page (dissoc m ::original-name ::original-title) @conn page-uuid per-file-state options)
-                                      (when (or (= "class" (:block/type m))
+                                      (when (or (ldb/class? m)
                                                 ;; Don't build a new page if it overwrites an existing class
                                                 (not (some-> (get @(:all-idents import-state)
                                                                   (some-> (or (::original-title m) (:block/title m))
@@ -1129,7 +1129,7 @@
                                                               (get-property-schema @(:property-schemas import-state) kw-name)
                                                               {:title (name kw-name)})]
                  (assert existing-page-uuid)
-                 (merge (select-keys new-prop [:block/type :block/schema :db/ident :db/index :db/cardinality :db/valueType])
+                 (merge (select-keys new-prop [:block/tags :block/schema :db/ident :db/index :db/cardinality :db/valueType])
                         {:block/uuid existing-page-uuid})))
              (set/intersection new-properties (set (map keyword (keys existing-pages)))))
         ;; Save properties on new property pages separately as they can contain new properties and thus need to be
@@ -1137,7 +1137,7 @@
         property-page-properties-tx (keep (fn [b]
                                             (when-let [page-properties (not-empty (db-property/properties b))]
                                               (merge page-properties {:block/uuid (:block/uuid b)
-                                                                      :block/type "property"})))
+                                                                      :block/tags (conj (:block/tags page-properties) :logseq.class/Property)})))
                                           properties-tx)]
     {:pages-tx pages-tx'
      :property-pages-tx (concat property-pages-tx converted-property-pages-tx)
@@ -1384,7 +1384,7 @@
 (defn- export-class-properties
   [conn repo-or-conn]
   (let [user-classes (->> (d/q '[:find (pull ?b [:db/id :db/ident])
-                                 :where [?b :block/type "class"]] @conn)
+                                 :where [?b :block/tags :logseq.class/Tag]] @conn)
                           (map first)
                           (remove #(db-class/built-in-classes (:db/ident %))))
         class-to-prop-uuids
@@ -1396,7 +1396,7 @@
                     [(contains? ?user-classes ?class)]
                     [?b ?prop _]
                     [?prop-e :db/ident ?prop]
-                    [?prop-e :block/type "property"]]
+                    [?prop-e :block/tags :logseq.class/Property]]
                   @conn
                   (set (map :db/ident user-classes)))
              (remove #(ldb/built-in? (d/entity @conn (second %))))

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

@@ -80,7 +80,8 @@
                                                                       (let [refs (:block/_refs page)]
                                                                         (and (or (zero? (count refs))
                                                                                  (= #{db-id} (set (map :db/id refs))))
-                                                                             (not (some #{"class" "property"} (:block/type page))))))}))]
+                                                                             (not (ldb/class? page))
+                                                                             (not (ldb/property? page)))))}))]
       (when (seq orphaned-pages)
         (let [tx (mapv (fn [page] [:db/retractEntity (:db/id page)]) orphaned-pages)]
           (swap! txs-state (fn [state] (vec (concat state tx)))))))))

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

@@ -553,7 +553,7 @@
           (when (seq values)
             (let [value-property-tx (map (fn [id]
                                            {:db/id id
-                                            :block/type "closed value"
+                                            :block/tags :logseq.class/Closed-Value
                                             :block/closed-value-property (:db/id property)})
                                          (map :db/id values))
                   property-tx (outliner-core/block-with-updated-at {:db/id (:db/id property)})]

+ 15 - 6
deps/outliner/test/logseq/outliner/validate_test.cljs

@@ -107,7 +107,15 @@
   (let [conn (db-test/create-conn)]
 
     (testing "Validate pages"
-      (let [pages (d/q '[:find [(pull ?b [*]) ...] :where [?b :block/title] [?b :block/type]] @conn)
+      (let [pages (->> (d/q '[:find [?b ...] :where
+                              [?b :block/title]
+                              (or [?b :block/tags :logseq.class/Class]
+                                  [?b :block/tags :logseq.class/Property]
+                                  [?b :block/tags :logseq.class/Page]
+                                  [?b :block/tags :logseq.class/Journal]
+                                  [?b :block/tags :logseq.class/Whiteboard])] @conn)
+                       (map (fn [id]
+                              (d/entity @conn id))))
             page-errors (atom {})]
         (doseq [page pages]
           (try
@@ -123,9 +131,10 @@
             "Default pages shouldn't have any validation errors")))
 
     (testing "Validate property relationships"
-      (let [parent-child-pairs (d/q '[:find (pull ?parent [:block/title :block/type])
-                                      (pull ?child [:block/title :block/type])
+      (let [parent-child-pairs (d/q '[:find ?parent ?child
                                       :where [?child :logseq.property/parent ?parent]] @conn)]
-        (doseq [[parent child] parent-child-pairs]
-          (is (nil? (outliner-validate/validate-parent-property parent [child]))
-              (str "Parent and child page is valid: " (pr-str (:block/title parent)) " " (pr-str (:block/title child)))))))))
+        (doseq [[parent-id child-id] parent-child-pairs]
+          (let [parent (d/entity @conn parent-id)
+                child (d/entity @conn child-id)]
+            (is (nil? (outliner-validate/validate-parent-property parent [child]))
+                (str "Parent and child page is valid: " (pr-str (:block/title parent)) " " (pr-str (:block/title child))))))))))

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

@@ -156,7 +156,7 @@
                            ;; reorder, shortest and starts-with first.
                            (let [matched-pages-with-new-page
                                  (fn [partial-matched-pages]
-                                   (if (or (db/page-exists? q (if db-tag? #{:logseq.class/Class} #{:logseq.class/Page}))
+                                   (if (or (db/page-exists? q (if db-tag? #{:logseq.class/Tag} #{:logseq.class/Page}))
                                            (and db-tag? (some ldb/class? (:block/_alias (db/get-page q)))))
                                      partial-matched-pages
                                      (if db-tag?

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

@@ -529,7 +529,6 @@
 (defn- get-property-values
   [rows property]
   (let [property-ident (:db/ident property)
-        block-type? (= property-ident :block/type)
         values (->> (mapcat (fn [e] (let [e' (db/entity (:db/id e))
                                           v (get e' property-ident)]
                                       (if (set? v) v #{v}))) rows)
@@ -537,9 +536,8 @@
                     (distinct))]
     (->>
      (map (fn [e]
-            (let [label (get-property-value-content e)
-                  label' (if (and block-type? (= label "class")) "tag" label)]
-              {:label (str label') :value e}))
+            (let [label (get-property-value-content e)]
+              {:label (str label) :value e}))
           values)
      (sort-by :label))))
 
@@ -607,7 +605,7 @@
                                  (do
                                    (shui/popup-hide!)
                                    (let [property internal-property
-                                         new-filter [(:db/ident property) (if (= (:db/ident property) :block/type) :is :text-contains)]
+                                         new-filter [(:db/ident property) :text-contains]
                                          filters' (if (seq filters)
                                                     (conj filters new-filter)
                                                     [new-filter])]
@@ -685,15 +683,14 @@
     [:before :after]
     (concat
      [:is :is-not]
-     (when-not (= :block/type (:db/ident property))
-       (case (get-in property [:block/schema :type])
-         (:default :url :node)
-         [:text-contains :text-not-contains]
-         (:date)
-         [:date-before :date-after]
-         :number
-         [:number-gt :number-lt :number-gte :number-lte :between]
-         nil)))))
+     (case (get-in property [:block/schema :type])
+       (:default :url :node)
+       [:text-contains :text-not-contains]
+       (:date)
+       [:date-before :date-after]
+       :number
+       [:number-gt :number-lt :number-gte :number-lte :between]
+       nil))))
 
 (defn- get-filter-with-changed-operator
   [_property operator value]
@@ -821,16 +818,11 @@
        {:class "!px-2 rounded-none border-r"
         :variant "ghost"
         :size :sm}
-       (let [block-type? (= (:db/ident property) :block/type)
-             value (cond
+       (let [value (cond
                      (uuid? value)
                      (db/entity [:block/uuid value])
                      (and (coll? value) (every? uuid? value))
                      (set (map #(db/entity [:block/uuid %]) value))
-                     (and block-type? (coll? value))
-                     (map (fn [v] (if (= v "class") "tag" v)) value)
-                     (and block-type? (= value "class"))
-                     "tag"
                      :else
                      value)]
          [:div.flex.flex-row.items-center.gap-1.text-xs
@@ -1012,15 +1004,15 @@
 (rum/defc new-record-button < rum/static
   [table view-entity]
   (let [asset? (and (:logseq.property/built-in? view-entity)
-                 (= (:block/name view-entity) "asset"))]
+                    (= (:block/name view-entity) "asset"))]
     (ui/tooltip
-      (shui/button
-        {:variant "ghost"
-         :class "!px-1 text-muted-foreground"
-         :size :sm
-         :on-click (get-in table [:data-fns :add-new-object!])}
-        (ui/icon (if asset? "upload" "plus")))
-      [:div "New record"])))
+     (shui/button
+      {:variant "ghost"
+       :class "!px-1 text-muted-foreground"
+       :size :sm
+       :on-click (get-in table [:data-fns :add-new-object!])}
+      (ui/icon (if asset? "upload" "plus")))
+     [:div "New record"])))
 
 (rum/defc add-new-row < rum/static
   [table]
@@ -1084,8 +1076,8 @@
         *rows-wrap (rum/use-ref nil)]
 
     (rum/use-effect!
-      (fn [] (set-ready? true))
-      [])
+     (fn [] (set-ready? true))
+     [])
 
     (shui/table
      (let [columns' (:columns table)
@@ -1097,17 +1089,17 @@
            (table-header table columns' option selected-rows)
 
            (ui/virtualized-list
-             {:ref #(reset! *scroller-ref %)
-              :custom-scroll-parent (or (some-> (rum/deref *rows-wrap) (.closest ".sidebar-item-list"))
-                                      (gdom/getElement "main-content-container"))
-              :increase-viewport-by {:top 300 :bottom 300}
-              :compute-item-key (fn [idx]
-                                  (let [block (nth rows idx)]
-                                    (str "table-row-" (:db/id block))))
-              :total-count (count rows)
-              :item-content (fn [idx]
-                              (let [row (nth rows idx)]
-                                (table-row table row columns' {} option)))})
+            {:ref #(reset! *scroller-ref %)
+             :custom-scroll-parent (or (some-> (rum/deref *rows-wrap) (.closest ".sidebar-item-list"))
+                                       (gdom/getElement "main-content-container"))
+             :increase-viewport-by {:top 300 :bottom 300}
+             :compute-item-key (fn [idx]
+                                 (let [block (nth rows idx)]
+                                   (str "table-row-" (:db/id block))))
+             :total-count (count rows)
+             :item-content (fn [idx]
+                             (let [row (nth rows idx)]
+                               (table-row table row columns' {} option)))})
 
            (when add-new-object!
              (shui/table-footer (add-new-row table)))])]))))

+ 1 - 1
src/main/frontend/db/model.cljs

@@ -801,7 +801,7 @@ independent of format as format specific heading characters are stripped"
   [repo & {:keys [except-root-class?]
            :or {except-root-class? false}}]
   (let [db (conn/get-db repo)
-        classes (->> (d/datoms db :avet :block/tags :logseq.class/Class)
+        classes (->> (d/datoms db :avet :block/tags :logseq.class/Tag)
                      (map (fn [d]
                             (db-utils/entity db (:e d)))))]
     (if except-root-class?

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

@@ -69,7 +69,7 @@
     {:db/id (:db/id page-entity)
      :block/title page-name
      :block/name (util/page-name-sanity-lc page-name)
-     :block/type "whiteboard"
+     :block/tags :logseq.class/Whiteboard
      :block/format :markdown
      :logseq.property/ls-type :whiteboard-page
      :logseq.property.tldraw/page tldraw-page

+ 24 - 1
src/main/frontend/worker/db/migrate.cljs

@@ -417,6 +417,27 @@
                 :block/title title'})))))
      datoms)))
 
+(defn- replace-block-type-with-tags
+  [conn _search-db]
+  (let [db @conn
+        datoms (d/datoms db :block/type)
+        journal-entity (d/entity db :logseq.class/Journal)
+        tx-data (map (fn [{:keys [e _a v]}]
+                       (let [tag (case v
+                                   "page" :logseq.class/Page
+                                   "class" :logseq.class/Tag
+                                   "property" :logseq.class/Property
+                                   "journal" :logseq.class/Journal
+                                   "whiteboard" :logseq.class/Whiteboard
+                                   "closed value" :logseq.class/Closed-Value
+                                   (throw (ex-info "unsupported block/type" {:type v})))]
+                         [[:db/retract e :block/type]
+                          [:db/add e :block/tags tag]])) datoms)]
+    (concat
+     ;; set journal's parent to `#Page`
+     [[:db/add (:db/id journal-entity) :logseq.property/parent :logseq.class/Page]]
+     tx-data)))
+
 (def schema-version->updates
   "A vec of tuples defining datascript migrations. Each tuple consists of the
    schema version integer and a migration map. A migration map can have keys of :properties, :classes
@@ -494,7 +515,9 @@
                      :logseq.property.attribute/property-schema-classes :logseq.property.attribute/property-value-content]}]
    [47 {:fix replace-hidden-type-with-schema}]
    [48 {:properties [:logseq.property/default-value :logseq.property/scalar-default-value]}]
-   [49 {:fix replace-special-id-ref-with-id-ref}]])
+   [49 {:fix replace-special-id-ref-with-id-ref}]
+   [50 {:classes [:logseq.class/Tag :logseq.class/Page :logseq.class/Whiteboard :logseq.class/Property :logseq.class/Closed-Value]}]
+   [51 {:fix replace-block-type-with-tags}]])
 
 (let [max-schema-version (apply max (map first schema-version->updates))]
   (assert (<= db-schema/version max-schema-version))

+ 6 - 12
src/main/frontend/worker/export.cljs

@@ -64,23 +64,17 @@
                          (:keys result)))))
            (group-by first)
            (mapcat (fn [[_id col]]
-                     (let [type (some (fn [[_e a v _t]]
-                                        (when (= a :block/type)
-                                          v)) col)
-                           ident (some (fn [[_e a v _t]]
+                     (let [ident (some (fn [[_e a v _t]]
                                          (when (= a :db/ident)
-                                           v)) col)]
+                                           v)) col)
+                           journal (some (fn [[_e a v _t]]
+                                           (when (= a :block/journal-day)
+                                             v)) col)]
                        (map
                         (fn [[e a v t]]
                           (cond
                             (and (contains? #{:block/title :block/name} a)
-                                 (or
-                                  ;; normal page or block
-                                  (not (contains? #{"class" "property" "journal" "closed value"} type))
-                                  ;; class/property created by user
-                                  (and ident
-                                       (contains? #{"class" "property"} type)
-                                       (not (string/starts-with? (namespace ident) "logseq")))))
+                                 (not (or ident journal)))
                             [e a (str "debug " e) t]
 
                             (= a :block/uuid)

+ 2 - 2
src/main/frontend/worker/handler/page/db_based/page.cljs

@@ -18,7 +18,7 @@
 
 (defn- build-page-tx [conn properties page {:keys [whiteboard? class? tags]}]
   (when (:block/uuid page)
-    (let [type-tag (cond class? :logseq.class/Class
+    (let [type-tag (cond class? :logseq.class/Tag
                          whiteboard? :logseq.class/Whiteboard
                          :else :logseq.class/Page)
           tags' (conj tags type-tag)
@@ -170,7 +170,7 @@
         date-formatter (:logseq.property.journal/title-format (d/entity db :logseq.class/Journal))
         title (sanitize-title title*)
         type (cond class?
-                   :logseq.class/Class
+                   :logseq.class/Tag
                    whiteboard?
                    :logseq.class/Whiteboard
                    today-journal?

+ 7 - 4
src/test/frontend/worker/handler/page/db_based/page_test.cljs

@@ -44,9 +44,12 @@
             "Child class with new parent has correct parents")
 
         (worker-db-page/create! conn "foo/class1/baz3" {:split-namespace? true})
-        (is (= #{"class" "page"}
-               (set (d/q '[:find [?type ...]
-                           :where [?b :block/type ?type] [?b :block/title "class1"]] @conn)))
+        (is (= #{"Class" "Page"}
+               (set (d/q '[:find [?tag-type ...]
+                           :where
+                           [?b :block/title "class1"]
+                           [?b :block/tags ?t]
+                           [?t :block/title ?tag-title]] @conn)))
             "Using an existing class page in a multi-parent namespace doesn't allow a page to have a class parent and instead creates a new page")))
 
     (testing "Child pages with same name and different parents"
@@ -85,4 +88,4 @@
          js/Error
          #"can't include \"/"
          (worker-db-page/create! conn "foo/bar" {}))
-        "Page can't have '/'n title")))
+        "Page can't have '/'n title")))