mirror of
https://github.com/logseq/logseq.git
synced 2026-06-01 19:01:22 +00:00
[wip] property edit
This commit is contained in:
@@ -140,7 +140,7 @@
|
||||
:uuid)
|
||||
latest-journal-blocks (when recent-journal
|
||||
(query repo db (str "select * from blocks where type = 1 and page_uuid = '" recent-journal "'")))
|
||||
init-data (query repo db "select * from blocks where type in (3, 4, 5)")]
|
||||
init-data (query repo db "select * from blocks where type in (3, 4, 5, 6)")]
|
||||
{:all-pages all-pages
|
||||
:all-blocks all-block-ids
|
||||
:journal-blocks latest-journal-blocks
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
[frontend.components.query.builder :as query-builder-component]
|
||||
[frontend.components.svg :as svg]
|
||||
[frontend.components.query :as query]
|
||||
[frontend.components.property :as property-component]
|
||||
[frontend.config :as config]
|
||||
[frontend.context.i18n :refer [t]]
|
||||
[frontend.date :as date]
|
||||
@@ -2813,17 +2814,17 @@
|
||||
(state/sub-block-selected? blocks-container-id uuid))]
|
||||
[:div.ls-block
|
||||
(cond->
|
||||
{:id block-id
|
||||
:data-refs data-refs
|
||||
:data-refs-self data-refs-self
|
||||
:data-collapsed (and collapsed? has-child?)
|
||||
:class (str uuid
|
||||
(when pre-block? " pre-block")
|
||||
(when (and card? (not review-cards?)) " shadow-md")
|
||||
(when selected? " selected noselect")
|
||||
(when (string/blank? content) " is-blank"))
|
||||
:blockid (str uuid)
|
||||
:haschild (str (boolean has-child?))}
|
||||
{:id block-id
|
||||
:data-refs data-refs
|
||||
:data-refs-self data-refs-self
|
||||
:data-collapsed (and collapsed? has-child?)
|
||||
:class (str uuid
|
||||
(when pre-block? " pre-block")
|
||||
(when (and card? (not review-cards?)) " shadow-md")
|
||||
(when selected? " selected noselect")
|
||||
(when (string/blank? content) " is-blank"))
|
||||
:blockid (str uuid)
|
||||
:haschild (str (boolean has-child?))}
|
||||
|
||||
level
|
||||
(assoc :level level)
|
||||
@@ -2878,6 +2879,8 @@
|
||||
|
||||
(when @*show-right-menu?
|
||||
(block-right-menu config block edit?))]
|
||||
(when (config/db-based-graph? repo)
|
||||
(property-component/properties-area block (:block/properties block)))
|
||||
|
||||
(block-children config block children collapsed?)
|
||||
|
||||
|
||||
257
src/main/frontend/components/property.cljs
Normal file
257
src/main/frontend/components/property.cljs
Normal file
@@ -0,0 +1,257 @@
|
||||
(ns frontend.components.property
|
||||
"Block properties management."
|
||||
(:require [frontend.ui :as ui]
|
||||
[frontend.util :as util]
|
||||
[clojure.string :as string]
|
||||
[frontend.handler.property :as property-handler]
|
||||
[frontend.db :as db]
|
||||
[rum.core :as rum]
|
||||
[frontend.state :as state]
|
||||
[goog.dom :as gdom]
|
||||
[frontend.search :as search]
|
||||
;; [frontend.components.search.highlight :as highlight]
|
||||
[frontend.components.svg :as svg]
|
||||
[frontend.modules.shortcut.core :as shortcut]
|
||||
[medley.core :as medley]))
|
||||
|
||||
;; (defn- add-property
|
||||
;; [entity k *new-property?]
|
||||
;; (when-not (string/blank? k)
|
||||
;; (property-handler/add-property! (:db/id entity) k)
|
||||
;; (reset! *new-property? false)))
|
||||
|
||||
;; (rum/defc search-item-render
|
||||
;; [search-q content]
|
||||
;; [:div.font-medium "TODO-search-item-render"
|
||||
;; ;; (highlight/highlight-exact-query content search-q)
|
||||
;; ])
|
||||
|
||||
;; (rum/defcs property-input <
|
||||
;; (shortcut/disable-all-shortcuts)
|
||||
;; (rum/local nil ::q)
|
||||
;; [state entity *new-property?]
|
||||
;; (let [*q (::q state)
|
||||
;; result (when-not (string/blank? @*q)
|
||||
;; (search/property-search @*q))]
|
||||
;; [:div
|
||||
;; [:div.ls-property-add.grid.grid-cols-4.flex.flex-row.items-center
|
||||
;; [:input#add-property.form-input.simple-input.block.col-span-1.focus:outline-none
|
||||
;; {:placeholder "Property key"
|
||||
;; :auto-focus true
|
||||
;; :on-change (fn [e]
|
||||
;; (reset! *q (util/evalue e)))
|
||||
;; :on-blur (fn [_e]
|
||||
;; (add-property entity @*q *new-property?))
|
||||
;; :on-key-up (fn [e]
|
||||
;; (case (util/ekey e)
|
||||
;; "Enter"
|
||||
;; (add-property entity @*q *new-property?)
|
||||
|
||||
;; "Escape"
|
||||
;; (reset! *new-property? false)
|
||||
|
||||
;; nil))}]
|
||||
;; [:a.close {:on-mouse-down #(do
|
||||
;; (reset! *q nil)
|
||||
;; (reset! *new-property? false))}
|
||||
;; svg/close]]
|
||||
;; (ui/auto-complete
|
||||
;; result
|
||||
;; {:class "search-results"
|
||||
;; :on-chosen #(add-property entity % *new-property?)
|
||||
;; :item-render #(search-item-render @*q %)})]))
|
||||
|
||||
(rum/defcs property-key < (rum/local false ::show-close?)
|
||||
[state entity k page-cp property-id ref-property?]
|
||||
(let [*show-close? (::show-close? state)]
|
||||
[:div.relative
|
||||
{:on-mouse-over (fn [_] (reset! *show-close? true))
|
||||
:on-mouse-out (fn [_] (reset! *show-close? false))}
|
||||
(page-cp {} {:block/name k})
|
||||
(when (and @*show-close? (not ref-property?))
|
||||
[:div.absolute.top-0.right-0
|
||||
[:a.fade-link.fade-in.py-2.px-1
|
||||
{:title "Remove this property"
|
||||
:on-click (fn [_e]
|
||||
(property-handler/delete-property! entity property-id))}
|
||||
(ui/icon "x")]])]))
|
||||
|
||||
(rum/defcs multiple-value-item < (rum/local false ::show-close?)
|
||||
[state entity property item dom-id' editor-id' {:keys [edit-fn page-cp inline-text]}]
|
||||
(let [*show-close? (::show-close? state)
|
||||
object? (= "object" (:type (:block/property-schema property)))]
|
||||
[:div.flex.flex-1.flex-row {:on-mouse-over #(reset! *show-close? true)
|
||||
:on-mouse-out #(reset! *show-close? false)}
|
||||
[:div.flex.flex-1.property-value-content
|
||||
{:id dom-id'
|
||||
:on-click (fn [] (edit-fn editor-id' dom-id' item))}
|
||||
(if object?
|
||||
(page-cp {} {:block/name (util/page-name-sanity-lc item)})
|
||||
(inline-text {} :markdown (str item)))]
|
||||
(when @*show-close?
|
||||
[:a.close.fade-in
|
||||
{:title "Delete this value"
|
||||
:on-mouse-down
|
||||
(fn []
|
||||
(property-handler/delete-property-value! entity (:block/uuid property) item))}
|
||||
svg/close])]))
|
||||
|
||||
(rum/defcs property-value < rum/reactive
|
||||
[state entity property k v k' {:keys [inline-text editor-box page-cp]}]
|
||||
(let [block (assoc entity :editing-property property)
|
||||
dom-id (str "ls-property-" k)
|
||||
editor-id (str "property-" (:db/id entity) "-" k')
|
||||
editing? (state/sub [:editor/editing? editor-id])
|
||||
schema (:block/property-schema property)
|
||||
edit-fn (fn [editor-id id v]
|
||||
(let [v (str v)
|
||||
cursor-range (util/caret-range (gdom/getElement (or id dom-id)))]
|
||||
(state/set-editing! editor-id v block cursor-range)
|
||||
(js/setTimeout
|
||||
(fn []
|
||||
(state/set-editor-action-data! {:property (:block/original-name property)
|
||||
:entity entity
|
||||
:pos 0})
|
||||
(state/set-editor-action! :property-value-search))
|
||||
50)))
|
||||
multiple-values? (:multiple-values? schema)
|
||||
type (:type schema)]
|
||||
(cond
|
||||
multiple-values?
|
||||
(let [v' (if (coll? v) v (when v [v]))
|
||||
v' (if (seq v') v' [""])
|
||||
editor-id' (str editor-id (count v'))
|
||||
new-editing? (state/sub [:editor/editing? editor-id'])]
|
||||
[:div.flex.flex-1.flex-col
|
||||
[:div.flex.flex-1.flex-col
|
||||
(for [[idx item] (medley/indexed v')]
|
||||
(let [dom-id' (str dom-id "-" idx)
|
||||
editor-id' (str editor-id idx)
|
||||
editing? (state/sub [:editor/editing? editor-id'])]
|
||||
(if editing?
|
||||
(editor-box {:format :markdown
|
||||
:block block} editor-id' {})
|
||||
(multiple-value-item entity property item dom-id' editor-id' {:page-cp page-cp
|
||||
:edit-fn edit-fn
|
||||
:inline-text inline-text}))))
|
||||
|
||||
(let [fv (first v')]
|
||||
(when (and (not new-editing?)
|
||||
fv
|
||||
(or (and (string? fv) (not (string/blank? fv)))
|
||||
(and (not (string? fv)) (some? fv))))
|
||||
[:div.rounded-sm.ml-1
|
||||
{:on-click (fn []
|
||||
(edit-fn (str editor-id (count v')) nil ""))}
|
||||
[:div.flex.flex-row
|
||||
[:div.block {:style {:height 20
|
||||
:width 20}}
|
||||
[:a.add-button-link.block {:title "Add another value"
|
||||
:style {:margin-left -4}}
|
||||
(ui/icon "circle-plus")]]]]))]
|
||||
(when new-editing?
|
||||
(editor-box {:format :markdown
|
||||
:block block} editor-id' {}))])
|
||||
|
||||
editing?
|
||||
(editor-box {:format :markdown
|
||||
:block block} editor-id {})
|
||||
|
||||
:else
|
||||
[:div.flex.flex-1.property-value-content
|
||||
{:id dom-id
|
||||
:on-click (fn []
|
||||
(edit-fn editor-id nil v))}
|
||||
(cond
|
||||
(and (= type "date") (string/blank? v))
|
||||
[:div "TBD (date icon)"]
|
||||
|
||||
:else
|
||||
(when-not (string/blank? (str v))
|
||||
(inline-text {} :markdown (str v))))])))
|
||||
|
||||
;; (rum/defcs properties-area <
|
||||
;; (rum/local false ::new-property?)
|
||||
;; rum/reactive
|
||||
;; [state entity properties refs-properties {:keys [page-cp inline-text]}]
|
||||
;; (let [*new-property? (::new-property? state)
|
||||
;; editor-box (state/get-component :editor/box)
|
||||
;; ref-keys (set (keys refs-properties))
|
||||
;; page? (:block/name entity)]
|
||||
;; [:div.ls-properties-area
|
||||
;; (when (seq properties)
|
||||
;; [:div
|
||||
;; (for [[k v] properties]
|
||||
;; (when-let [property (db/pull [:block/uuid k])]
|
||||
;; (when-let [k' (:block/original-name property)]
|
||||
;; (let [ref-property? (contains? ref-keys k)]
|
||||
;; [:div.grid.grid-cols-4.gap-1
|
||||
;; [:div.property-key.col-span-1
|
||||
;; (property-key entity k' page-cp k ref-property?)]
|
||||
|
||||
;; [:div.col-span-3
|
||||
;; (property-value entity property k v k' {:page-cp page-cp
|
||||
;; :inline-text inline-text
|
||||
;; :editor-box editor-box})]]))))])
|
||||
|
||||
;; (when page?
|
||||
;; (if @*new-property?
|
||||
;; (property-input entity *new-property?)
|
||||
;; [:div.flex-1.flex-col.rounded-sm
|
||||
;; {:on-click (fn []
|
||||
;; (reset! *new-property? true))}
|
||||
;; [:div.flex.flex-row
|
||||
;; [:div.block {:style {:height 20
|
||||
;; :width 20}}
|
||||
;; [:a.add-button-link.block {:title "Add another property"
|
||||
;; :style {:margin-left -4}}
|
||||
;; (ui/icon "circle-plus")]]]]))]))
|
||||
|
||||
;; (rum/defc composed-properties < rum/reactive
|
||||
;; [entity refs block-components-m]
|
||||
;; (let [namespaces (map :block/namespace (distinct refs))
|
||||
;; refs-properties (map
|
||||
;; (fn [ref]
|
||||
;; (:block/properties
|
||||
;; (db/pull (:db/id ref))))
|
||||
;; (concat namespaces refs))
|
||||
;; property-maps (concat refs-properties
|
||||
;; [(:block/properties entity)])
|
||||
;; properties (apply merge property-maps)
|
||||
;; refs-properties' (apply merge refs-properties)]
|
||||
;; (properties-area entity properties refs-properties' block-components-m)))
|
||||
|
||||
(rum/defcs properties-area <
|
||||
(rum/local nil ::new-property)
|
||||
rum/reactive
|
||||
[state block properties]
|
||||
(let [*new-property (::new-property state)
|
||||
repo (state/get-current-repo)]
|
||||
[:div.ls-properties-area.pl-6
|
||||
(when (seq properties)
|
||||
(prn :properties properties)
|
||||
[:div
|
||||
(for [[prop-uuid-or-built-in-prop v] properties]
|
||||
(if (uuid? prop-uuid-or-built-in-prop)
|
||||
(when-let [property-class (db/pull [:block/uuid prop-uuid-or-built-in-prop])]
|
||||
[:div
|
||||
[:a.mr-2 (:property/name property-class)]
|
||||
[:input {:value v}]])
|
||||
;; builtin
|
||||
[:div
|
||||
[:a.mr-2 (str prop-uuid-or-built-in-prop)]
|
||||
[:input {:value v}]]))])
|
||||
(if (nil? @*new-property)
|
||||
[:a {:title "Add another value"
|
||||
:on-click (fn [] (reset! *new-property {}))}
|
||||
(ui/icon "circle-plus")]
|
||||
|
||||
[:div
|
||||
[:input.block-properties {:on-change #(swap! *new-property assoc :k (util/evalue %))}]
|
||||
[:input.block-properties {:on-change #(swap! *new-property assoc :v (util/evalue %))}]
|
||||
[:a {:on-click (fn []
|
||||
(when (and (:k @*new-property) (:k @*new-property))
|
||||
(prn :*new-property @*new-property)
|
||||
(property-handler/add-property! repo block (:k @*new-property) (:v @*new-property))
|
||||
(reset! *new-property nil)))}
|
||||
"Save"]])]))
|
||||
@@ -101,7 +101,7 @@
|
||||
(let [all-datoms (persistent! datoms)
|
||||
new-db (util/profile
|
||||
(str "DB init! " (count all-datoms) " datoms")
|
||||
(d/init-db all-datoms db-schema/schema))]
|
||||
(d/init-db all-datoms db-schema/schema-for-db-based-graph))]
|
||||
|
||||
(reset! conn new-db)
|
||||
|
||||
@@ -174,7 +174,7 @@
|
||||
all-eav-coll)
|
||||
db-name (db-conn/datascript-db repo)
|
||||
db-conn (util/profile :restore-graph-from-sqlite!-init-db
|
||||
(d/conn-from-datoms datoms db-schema/schema))
|
||||
(d/conn-from-datoms datoms db-schema/schema-for-db-based-graph))
|
||||
_ (swap! db-conn/conns assoc db-name db-conn)
|
||||
end-time (t/now)]
|
||||
(println :restore-graph-from-sqlite!-prepare (t/in-millis (t/interval start-time end-time)) "ms"
|
||||
|
||||
152
src/main/frontend/handler/property.cljs
Normal file
152
src/main/frontend/handler/property.cljs
Normal file
@@ -0,0 +1,152 @@
|
||||
(ns frontend.handler.property
|
||||
"Block properties handler."
|
||||
(:require [frontend.state :as state]
|
||||
[frontend.db :as db]
|
||||
[frontend.util :as util]
|
||||
[frontend.format.block :as block]
|
||||
[clojure.string :as string]
|
||||
[logseq.graph-parser.mldoc :as gp-mldoc]
|
||||
[logseq.graph-parser.block :as gp-block]
|
||||
[logseq.graph-parser.util :as gp-util]
|
||||
[logseq.graph-parser.util.page-ref :as page-ref]
|
||||
[frontend.modules.outliner.core :as outliner-core]
|
||||
[frontend.modules.outliner.transaction :as outliner-tx]
|
||||
[frontend.util.property-edit :as property-edit]))
|
||||
|
||||
(defn add-property!
|
||||
[repo block k v]
|
||||
(let [tx-data (property-edit/insert-property-when-db-based repo block k v)]
|
||||
(db/transact! repo tx-data)))
|
||||
|
||||
(defn remove-property!
|
||||
[repo block k]
|
||||
(let [tx-data (property-edit/remove-property-when-db-based block k)]
|
||||
(db/transact! repo tx-data)))
|
||||
|
||||
|
||||
;; (defn add-property!
|
||||
;; [block-db-id key]
|
||||
;; (let [block (db/pull block-db-id)
|
||||
;; key (string/trim key)
|
||||
;; key-name (util/page-name-sanity-lc key)
|
||||
;; property (db/entity [:block/name key-name])]
|
||||
;; (when-not (or
|
||||
;; (= (:block/name block) key-name)
|
||||
;; (and property
|
||||
;; (or
|
||||
;; (= (:block/type property) "tag")
|
||||
;; (= (:db/id property) (:db/id block)))))
|
||||
;; (let [property-uuid (db/new-block-id)]
|
||||
;; (db/transact! (state/get-current-repo)
|
||||
;; [
|
||||
;; ;; property
|
||||
;; {:block/uuid property-uuid
|
||||
;; :block/type "property"
|
||||
;; :block/property-schema {:type "any"}
|
||||
;; :block/original-name key
|
||||
;; :block/name key-name}
|
||||
|
||||
;; {:block/uuid (:block/uuid block)
|
||||
;; :block/properties (assoc (:block/properties block)
|
||||
;; property-uuid "")}])))))
|
||||
|
||||
(defn- extract-refs
|
||||
[entity properties]
|
||||
(let [property-values (->>
|
||||
properties
|
||||
(map (fn [[k v]]
|
||||
(let [schema (:block/property-schema (db/pull [:block/uuid k]))
|
||||
object? (= (:type schema) "object")
|
||||
f (if object? page-ref/->page-ref identity)]
|
||||
(->> (if (coll? v)
|
||||
v
|
||||
[v])
|
||||
(map f)))))
|
||||
(apply concat)
|
||||
(filter string?))
|
||||
block-text (string/join " "
|
||||
(cons
|
||||
(:block/content entity)
|
||||
property-values))
|
||||
ast-refs (gp-mldoc/get-references block-text (gp-mldoc/default-config :markdown))
|
||||
refs (map #(or (gp-block/get-page-reference % #{})
|
||||
(gp-block/get-block-reference %)) ast-refs)
|
||||
refs' (->> refs
|
||||
(remove string/blank?)
|
||||
distinct)]
|
||||
(map #(if (util/uuid-string? %)
|
||||
[:block/uuid (uuid %)]
|
||||
(block/page-name->map % true)) refs')))
|
||||
|
||||
(defn delete-property!
|
||||
[entity property-id]
|
||||
(when (and entity (uuid? property-id))
|
||||
(let [properties' (dissoc (:block/properties entity) property-id)
|
||||
refs (extract-refs entity properties')]
|
||||
(outliner-tx/transact!
|
||||
{:outliner-op :save-block}
|
||||
(outliner-core/save-block!
|
||||
{:block/uuid (:block/uuid entity)
|
||||
:block/properties properties'
|
||||
:block/refs refs})))))
|
||||
|
||||
(defn validate
|
||||
"Check whether the `value` validate against the `schema`."
|
||||
[schema value]
|
||||
(if (string/blank? value)
|
||||
[true value]
|
||||
(case (:type schema)
|
||||
"any" [true value]
|
||||
"number" (if-let [n (parse-double value)]
|
||||
(let [[min-n max-n] [(:min schema) (:max schema)]
|
||||
min-result (if min-n (>= n min-n) true)
|
||||
max-result (if max-n (<= n max-n) true)]
|
||||
(cond
|
||||
(and min-result max-result)
|
||||
[true n]
|
||||
|
||||
(false? min-result)
|
||||
[false (str "the min value is " min-n)]
|
||||
|
||||
(false? max-result)
|
||||
[false (str "the max value is " max-n)]
|
||||
|
||||
:else
|
||||
n))
|
||||
[false "invalid number"])
|
||||
"date" (if-let [result (js/Date. value)]
|
||||
(if (not= (str result) "Invalid Date")
|
||||
[true value]
|
||||
[false "invalid date"])
|
||||
[false "invalid date"])
|
||||
"url" (if (gp-util/url? value)
|
||||
[true value]
|
||||
[false "invalid URL"])
|
||||
"object" (let [page-name (or
|
||||
(try
|
||||
(page-ref/get-page-name value)
|
||||
(catch :default _))
|
||||
value)]
|
||||
[true page-name]))))
|
||||
|
||||
(defn delete-property-value!
|
||||
"Delete value if a property has multiple values"
|
||||
[entity property-id property-value]
|
||||
(when (and entity (uuid? property-id))
|
||||
(when (not= property-id (:block/uuid entity))
|
||||
(when-let [property (db/pull [:block/uuid property-id])]
|
||||
(let [schema (:block/property-schema property)
|
||||
[success? property-value-or-error] (validate schema property-value)
|
||||
multiple-values? (:multiple-values? schema)]
|
||||
(when (and multiple-values? success?)
|
||||
(let [properties (:block/properties entity)
|
||||
properties' (update properties property-id disj property-value-or-error)
|
||||
refs (extract-refs entity properties')]
|
||||
(outliner-tx/transact!
|
||||
{:outliner-op :save-block}
|
||||
(outliner-core/save-block!
|
||||
{:block/uuid (:block/uuid entity)
|
||||
:block/properties properties'
|
||||
:block/refs refs}))))
|
||||
(state/clear-editor-action!)
|
||||
(state/clear-edit!))))))
|
||||
@@ -52,6 +52,8 @@
|
||||
(state/set-current-repo! "local")
|
||||
(when-let [data js/window.logseq_db]
|
||||
(let [data (unescape-html data)
|
||||
;; FIXME: how to decide which schema to use here?
|
||||
;; db-schema/schema or db-schema/schema-for-db-based-graph?
|
||||
db-conn (d/create-conn db-schema/schema)
|
||||
_ (swap! db/conns assoc "logseq-db/local" db-conn)
|
||||
db (db/string->db data)]
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
(ns frontend.util.property-edit
|
||||
"Property related fns, both file-based and db-based version need to be considered."
|
||||
(:require [frontend.util.property :as property]
|
||||
[frontend.config :as config]))
|
||||
[frontend.config :as config]
|
||||
[frontend.db :as db]))
|
||||
|
||||
|
||||
;; Why need these XXX-when-file-based fns?
|
||||
@@ -64,3 +65,26 @@
|
||||
(def property-key-exist?-when-file-based property/property-key-exist?)
|
||||
(def goto-properties-end-when-file-based property/goto-properties-end)
|
||||
(def front-matter?-when-file-based property/front-matter?)
|
||||
|
||||
|
||||
(defn insert-property-when-db-based
|
||||
"return tx-data"
|
||||
[repo block k-name v]
|
||||
(let [property-class (db/pull repo '[*] [:property/name k-name])
|
||||
property-class-uuid (or (:block/uuid property-class) (random-uuid))]
|
||||
(cond-> []
|
||||
(nil? property-class) (conj {:property/schema {}
|
||||
:property/name k-name
|
||||
:block/uuid property-class-uuid
|
||||
:block/type "property"})
|
||||
true (conj {:block/uuid (:block/uuid block)
|
||||
:block/properties (assoc (:block/properties block) (str property-class-uuid) v)}))))
|
||||
|
||||
(defn remove-property-when-db-based
|
||||
"return tx-data"
|
||||
[block k-uuid-or-builtin-k-name]
|
||||
{:pre (string? k-uuid-or-builtin-k-name)}
|
||||
(let [origin-properties (:block/properties block)]
|
||||
(assert (contains? (set (keys origin-properties)) k-uuid-or-builtin-k-name))
|
||||
[{:block/uuid (:block/uuid block)
|
||||
:block/properties (dissoc origin-properties k-uuid-or-builtin-k-name)}]))
|
||||
|
||||
Reference in New Issue
Block a user