Browse Source

enhance: bring back built-in properties using closed values

Fixes LOG-2903. Also fixed a bug with logseq.color property
not working with latest accent color
Gabriel Horner 1 year ago
parent
commit
e847c0899a

+ 1 - 0
deps/db/.carve/config.edn

@@ -6,6 +6,7 @@
                   logseq.db.sqlite.cli
                   logseq.db.frontend.property
                   logseq.db.frontend.property.util
+                  logseq.db.sqlite.create-graph
                   logseq.db.frontend.malli-schema
                   ;; Some fns are used by frontend but not worth moving over yet
                   logseq.db.frontend.schema]

+ 10 - 0
deps/db/src/logseq/db/frontend/property.cljs

@@ -46,6 +46,10 @@
    ;; color props
    :logseq.color {:schema
                   {:type :default :hide? true}
+                  :closed-values
+                  (mapv #(hash-map :value % :uuid (random-uuid))
+                        ;; Stringified version of frontend.colors/COLORS. Too basic to couple
+                        ["tomato" "red" "crimson" "pink" "plum" "purple" "violet" "indigo" "blue" "cyan" "teal" "green" "grass" "orange" "brown"])
                   :visible true}
    ;; table-v2 props
    :logseq.table.version {:schema {:type :number :hide? true}
@@ -54,9 +58,15 @@
                           :visible true}
    :logseq.table.headers {:schema
                           {:type :default :hide? true}
+                          :closed-values
+                          (mapv #(hash-map :value % :uuid (random-uuid))
+                                ["uppercase" "capitalize" "capitalize-first" "lowercase"])
                           :visible true}
    :logseq.table.hover {:schema
                         {:type :default :hide? true}
+                        :closed-values
+                        (mapv #(hash-map :value % :uuid (random-uuid))
+                              ["row" "col" "both" "none"])
                         :visible true}
    :logseq.table.borders {:schema {:type :checkbox :hide? true}
                           :visible true}

+ 35 - 0
deps/db/src/logseq/db/frontend/property/util.cljs

@@ -45,3 +45,38 @@
     (-> (build-new-page page-name)
         (assoc :block/type #{"hidden"}
                :block/format :markdown))))
+
+(defn new-property-tx
+  "Provide attributes for a new built-in property given name, schema and uuid.
+   TODO: Merge this with sqlite-util/build-new-property once gp-util/page-name-sanity-lc
+   is available to deps/db"
+  [prop-name prop-schema prop-uuid]
+  {:block/uuid prop-uuid
+   :block/schema (merge {:type :default} prop-schema)
+   :block/original-name (name prop-name)
+   :block/name (sqlite-util/sanitize-page-name (name prop-name))})
+
+(defn build-closed-values
+  "Builds all the tx needed for property with closed values including
+   the hidden page and closed value blocks as needed"
+  [prop-name property {:keys [icon-id translate-closed-page-value-fn property-attributes]
+                       :or {translate-closed-page-value-fn identity}}]
+  (let [page-tx (build-property-hidden-page property)
+        page-id [:block/uuid (:block/uuid page-tx)]
+        closed-value-page-uuids? (contains? #{:page :date} (get-in property [:block/schema :type]))
+        closed-value-blocks-tx
+        (if closed-value-page-uuids?
+          (map translate-closed-page-value-fn (:closed-values property))
+          (map (fn [{:keys [value icon description uuid]}]
+                 (build-closed-value-block
+                  uuid value page-id property {:icon-id icon-id
+                                               :icon icon
+                                               :description description}))
+               (:closed-values property)))
+        property-schema (assoc (:block/schema property)
+                               :values (mapv :block/uuid closed-value-blocks-tx))
+        property-tx (merge (sqlite-util/build-new-property
+                            (new-property-tx prop-name property-schema (:block/uuid property)))
+                           property-attributes)]
+    (into [property-tx page-tx]
+          (when-not closed-value-page-uuids? closed-value-blocks-tx))))

+ 36 - 0
deps/db/src/logseq/db/sqlite/create_graph.cljs

@@ -0,0 +1,36 @@
+(ns logseq.db.sqlite.create-graph
+  "Helper fns for creating a DB graph"
+  (:require [logseq.db.sqlite.util :as sqlite-util]
+            [logseq.db.frontend.property :as db-property]
+            [logseq.db.frontend.property.util :as db-property-util]
+            [datascript.core :as d]))
+
+(defn build-db-initial-data
+  [config-content]
+  (let [initial-files [{:block/uuid (d/squuid)
+                        :file/path (str "logseq/" "config.edn")
+                        :file/content config-content
+                        :file/last-modified-at (js/Date.)}
+                       {:block/uuid (d/squuid)
+                        :file/path (str "logseq/" "custom.css")
+                        :file/content ""
+                        :file/last-modified-at (js/Date.)}
+                       {:block/uuid (d/squuid)
+                        :file/path (str "logseq/" "custom.js")
+                        :file/content ""
+                        :file/last-modified-at (js/Date.)}]
+        default-properties (mapcat
+                            (fn [[k-keyword {:keys [schema original-name closed-values]}]]
+                              (let [k-name (name k-keyword)]
+                                (if closed-values
+                                  (db-property-util/build-closed-values
+                                   (or original-name k-name)
+                                   {:block/schema schema :block/uuid (d/squuid) :closed-values closed-values}
+                                   {})
+                                  [(sqlite-util/build-new-property
+                                    {:block/schema schema
+                                     :block/original-name (or original-name k-name)
+                                     :block/name (sqlite-util/sanitize-page-name k-name)
+                                     :block/uuid (d/squuid)})])))
+                            db-property/built-in-properties)]
+    (concat initial-files default-properties)))

+ 2 - 29
deps/db/src/logseq/db/sqlite/util.cljs

@@ -4,9 +4,7 @@
             [cljs-time.core :as t]
             [clojure.string :as string]
             [cognitect.transit :as transit]
-            [datascript.core :as d]
-            [logseq.db.frontend.schema :as db-schema]
-            [logseq.db.frontend.property :as db-property]))
+            [logseq.db.frontend.schema :as db-schema]))
 
 (defn- type-of-block
   "
@@ -96,29 +94,4 @@
    (merge {:block/type "property"
            :block/journal? false
            :block/format :markdown}
-          block)))
-
-(defn build-db-initial-data
-  [config-content]
-  (let [initial-files [{:block/uuid (d/squuid)
-                        :file/path (str "logseq/" "config.edn")
-                        :file/content config-content
-                        :file/last-modified-at (js/Date.)}
-                       {:block/uuid (d/squuid)
-                        :file/path (str "logseq/" "custom.css")
-                        :file/content ""
-                        :file/last-modified-at (js/Date.)}
-                       {:block/uuid (d/squuid)
-                        :file/path (str "logseq/" "custom.js")
-                        :file/content ""
-                        :file/last-modified-at (js/Date.)}]
-        default-properties (map
-                            (fn [[k-keyword {:keys [schema original-name]}]]
-                              (let [k-name (name k-keyword)]
-                                (build-new-property
-                                 {:block/schema schema
-                                  :block/original-name (or original-name k-name)
-                                  :block/name (sanitize-page-name k-name)
-                                  :block/uuid (d/squuid)})))
-                            db-property/built-in-properties)]
-    (concat initial-files default-properties)))
+          block)))

+ 16 - 38
scripts/src/logseq/tasks/db_graph/create_graph.cljs

@@ -5,6 +5,7 @@
   graph and current limitations"
   (:require [logseq.db.sqlite.db :as sqlite-db]
             [logseq.db.sqlite.util :as sqlite-util]
+            [logseq.db.sqlite.create-graph :as sqlite-create-graph]
             [logseq.db.frontend.property.util :as db-property-util]
             [logseq.outliner.cli.persist-graph :as persist-graph]
             [logseq.db :as ldb]
@@ -28,7 +29,7 @@
   (let [config-content (or (some-> (find-on-classpath "templates/config.edn") fs/readFileSync str)
                            (do (println "Setting graph's config to empty since no templates/config.edn was found.")
                                "{}"))]
-    (d/transact! conn (sqlite-util/build-db-initial-data config-content))))
+    (d/transact! conn (sqlite-create-graph/build-db-initial-data config-content))))
 
 (defn init-conn
   "Create sqlite DB, initialize datascript connection and sync listener and then
@@ -121,35 +122,6 @@
            {:block/properties (->block-properties-tx (:properties m) uuid-maps)
             :block/refs (build-property-refs (:properties m) property-db-ids)})))
 
-(defn- ->property-tx
-  [prop-name prop-schema prop-uuid property-db-ids]
-  {:db/id (or (property-db-ids (name prop-name))
-              (throw (ex-info "No :db/id for property" {:property prop-name})))
-   :block/uuid prop-uuid
-   :block/schema (merge {:type :default} prop-schema)
-   :block/original-name (name prop-name)
-   :block/name (sqlite-util/sanitize-page-name (name prop-name))})
-
-(defn- build-closed-values-tx [prop-name {:block/keys [uuid] :as property} property-db-ids uuid-maps icon-id]
-  (let [page-tx (db-property-util/build-property-hidden-page property)
-        page-id [:block/uuid (:block/uuid page-tx)]
-        closed-value-page-uuids? (contains? #{:page :date} (get-in property [:block/schema :type]))
-        closed-value-blocks-tx
-        (if closed-value-page-uuids?
-          (map #(hash-map :block/uuid (translate-property-value (:value %) uuid-maps))
-               (:closed-values property))
-          (map (fn [{:keys [value icon description uuid]}]
-                 (db-property-util/build-closed-value-block
-                  uuid value page-id property {:icon-id icon-id
-                                               :icon icon
-                                               :description description}))
-               (:closed-values property)))
-        property-schema (assoc (:block/schema property)
-                               :values (mapv :block/uuid closed-value-blocks-tx))
-        property-tx (sqlite-util/build-new-property (->property-tx prop-name property-schema uuid property-db-ids))]
-    (into [property-tx page-tx]
-          (when-not closed-value-page-uuids? closed-value-blocks-tx))))
-
 (defn create-blocks-tx
   "Given an EDN map for defining pages, blocks and properties, this creates a
   vector of transactable data for use with d/transact!. The blocks that can be created
@@ -169,7 +141,7 @@
        :block/content is required and :properties can be passed to define block properties
    * :properties - This is a map to configure properties where the keys are property names
      and the values are maps of datascript attributes e.g. `{:block/schema {:type :checkbox}}`.
-     Within `:block/schema`, closed values can be defined with :closed-values. The key takes
+     An additional key `:closed-values` is available to define closed values. The key takes
      a vec of maps containing keys :uuid, :value and :icon.
 
    The :properties for :pages-and-blocks is a map of property names to property
@@ -196,14 +168,20 @@
                            (mapcat
                             (fn [[prop-name uuid]]
                               (if (get-in properties [prop-name :closed-values])
-                                (build-closed-values-tx prop-name
-                                                        (assoc (get properties prop-name)
-                                                               :block/uuid uuid)
-                                                        property-db-ids
-                                                        uuid-maps
-                                                        (get-in options [:property-uuids :icon]))
+                                (db-property-util/build-closed-values
+                                 prop-name
+                                 (assoc (get properties prop-name) :block/uuid uuid)
+                                 {:icon-id
+                                  (get-in options [:property-uuids :icon])
+                                  :translate-closed-page-value-fn
+                                  #(hash-map :block/uuid (translate-property-value (:value %) uuid-maps))
+                                  :property-attributes
+                                  {:db/id (or (property-db-ids (name prop-name))
+                                              (throw (ex-info "No :db/id for property" {:property prop-name})))}})
                                 [(sqlite-util/build-new-property
-                                  (merge (->property-tx prop-name (get-in properties [prop-name :block/schema]) uuid property-db-ids)
+                                  (merge (db-property-util/new-property-tx prop-name (get-in properties [prop-name :block/schema]) uuid)
+                                         {:db/id (or (property-db-ids (name prop-name))
+                                                     (throw (ex-info "No :db/id for property" {:property prop-name})))}
                                          (when-let [props (not-empty (get-in properties [prop-name :properties]))]
                                            {:block/properties (->block-properties-tx props uuid-maps)
                                             :block/refs (build-property-refs props property-db-ids)})))]))

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

@@ -63,7 +63,7 @@
 
 
 (defn linear-gradient [color-name color-stop gradient-level]
-  (let [color-index (.indexOf color-list color-name)
+  (let [color-index (.indexOf color-list (keyword color-name))
         step (fn [dist]
                (str "var(--rx-"
                  (name (nth color-list (mod (+ color-index dist) (count color-list))))

+ 22 - 14
src/main/frontend/db/restore.cljs

@@ -2,7 +2,6 @@
   "Fns for DB restore(from text or sqlite)"
   (:require [datascript.core :as d]
             [frontend.config :as config]
-            [frontend.db :as db]
             [frontend.db.conn :as db-conn]
             [frontend.db.file-based.migrate :as db-migrate]
             [frontend.db.persist :as db-persist]
@@ -17,7 +16,8 @@
             [promesa.core :as p]
             [frontend.util :as util]
             [cljs-time.core :as t]
-            [logseq.db.frontend.property :as db-property]))
+            [logseq.db.frontend.property :as db-property]
+            [logseq.db.frontend.property.util :as db-property-util]))
 
 (defn- old-schema?
   "Requires migration if the schema version is older than db-schema/version"
@@ -66,26 +66,34 @@
 
 (defn- update-built-in-properties!
   [conn]
-  (let [txs (keep
-             (fn [[k-keyword {:keys [schema original-name]}]]
+  (let [txs (mapcat
+             (fn [[k-keyword {:keys [schema original-name] :as property-config}]]
                (let [k-name (name k-keyword)
                      property (d/entity @conn [:block/name k-name])]
-                 (when-not (= {:schema schema
+                 (when (and
+                        (not= {:schema schema
                                :original-name (or original-name k-name)}
                               {:schema (:block/schema property)
                                :original-name (:block/original-name property)})
+                         ;; Updating closed values disabled until it's worth the effort
+                         ;; to diff closed values
+                        (not (:closed-values property-config)))
                    (if property
-                     {:block/schema schema
-                      :block/original-name (or original-name k-name)
-                      :block/name (util/page-name-sanity-lc k-name)
-                      :block/uuid (:block/uuid property)
-                      :block/type "property"}
-                     (sqlite-util/block-with-timestamps
-                      {:block/schema schema
+                     [{:block/schema schema
                        :block/original-name (or original-name k-name)
                        :block/name (util/page-name-sanity-lc k-name)
-                       :block/uuid (db/new-block-id)
-                       :block/type "property"})))))
+                       :block/uuid (:block/uuid property)
+                       :block/type "property"}]
+                     (if (:closed-values property-config)
+                       (db-property-util/build-closed-values
+                        (or original-name k-name)
+                        (assoc property-config :block/uuid (d/squuid))
+                        {})
+                       [(sqlite-util/build-new-property
+                         {:block/schema schema
+                          :block/original-name (or original-name k-name)
+                          :block/name (util/page-name-sanity-lc k-name)
+                          :block/uuid (d/squuid)})])))))
              db-property/built-in-properties)]
     (when (seq txs)
       (d/transact! conn txs))))

+ 2 - 2
src/main/frontend/handler/repo.cljs

@@ -27,7 +27,7 @@
             [frontend.db.persist :as db-persist]
             [logseq.graph-parser :as graph-parser]
             [logseq.graph-parser.config :as gp-config]
-            [logseq.db.sqlite.util :as sqlite-util]
+            [logseq.db.sqlite.create-graph :as sqlite-create-graph]
             [electron.ipc :as ipc]
             [cljs-bean.core :as bean]
             [clojure.core.async :as async]
@@ -545,7 +545,7 @@
           _ (start-repo-db-if-not-exists! full-graph-name)
           _ (state/add-repo! {:url full-graph-name})
           _ (route-handler/redirect-to-home!)
-          initial-data (sqlite-util/build-db-initial-data config/config-default-content)
+          initial-data (sqlite-create-graph/build-db-initial-data config/config-default-content)
           _ (db/transact! full-graph-name initial-data)
           _ (repo-config-handler/set-repo-config-state! full-graph-name config/config-default-content)
           ;; TODO: handle global graph