enhance(ux): set/unset #Page to convert between page and block (#11970)

* enhance(ux): add/remove #Page to toggle page/block

* enhance(ux): "p t" to set tags for selected blocks

Updated "p a" to toggle displaying all properties including hidden ones.

* feat: cmd+k move blocks

* fix: block could be converted to page and create invalid nodes

Pages with block namespace parents is nonsensical and pages in
property values led to multiple validation errors. Also guard
against class and property pages as namespace parents

* fix: warn on failed cut+paste or indent/outdent of page blocks. Better to warn than silent failure which leaves user confused on
what happened. 

---------

Co-authored-by: Gabriel Horner <gabriel@logseq.com>
This commit is contained in:
Tienson Qin
2025-08-05 17:45:57 +08:00
committed by GitHub
parent a2eee34d80
commit d84d3f9652
39 changed files with 950 additions and 435 deletions

View File

@@ -249,8 +249,7 @@
(p/do!
(ui-outliner-tx/transact!
{:outliner-op :save-block}
(doseq [block blocks]
(db-property-handler/delete-property-value! (:db/id block) (:db/ident property) value)))
(db-property-handler/batch-delete-property-value! (map :db/id blocks) (:db/ident property) value))
(when (or (not many?)
;; values will be cleared
(and many? (<= (count (get block (:db/ident property))) 1)))
@@ -698,10 +697,13 @@
excluded-options)
(contains? #{:class :property} property-type)
(let [classes (model/get-all-classes
repo
{:except-root-class? true
:except-private-tags? (not (contains? #{:logseq.property/template-applied-to} (:db/ident property)))})]
(let [classes (cond->
(model/get-all-classes
repo
{:except-root-class? true
:except-private-tags? (not (contains? #{:logseq.property/template-applied-to} (:db/ident property)))})
(not (or (and (entity-util/page? block) (not (ldb/internal-page? block))) (:logseq.property/created-from-property block)))
(conj (db/entity :logseq.class/Page)))]
(if (= property-type :class)
classes
(property-handler/get-class-property-choices)))
@@ -771,7 +773,8 @@
:label label
:value id
:disabled? (and tags? (contains?
(set/union #{:logseq.class/Journal :logseq.class/Whiteboard} ldb/internal-tags)
(set/union #{:logseq.class/Journal :logseq.class/Whiteboard}
(set/difference ldb/internal-tags #{:logseq.class/Page}))
(:db/ident node)))))) nodes)
classes' (remove (fn [class] (= :logseq.class/Root (:db/ident class))) classes)
opts' (cond->
@@ -788,13 +791,12 @@
"Set alias"
:else
(str "Set " (:block/title property)))
:show-new-when-not-exact-match? (if (or extends-property?
;; Don't allow creating private tags
(and (= :block/tags (:db/ident property))
(seq (set/intersection (set (map :db/ident classes'))
ldb/private-tags))))
false
true)
:show-new-when-not-exact-match? (not
(or (and extends-property? (contains? (set children-pages) (:db/id block)))
;; Don't allow creating private tags
(and (= :block/tags (:db/ident property))
(seq (set/intersection (set (map :db/ident classes'))
ldb/private-tags)))))
:extract-chosen-fn :value
:extract-fn (fn [x] (or (:label-value x) (:label x)))
:input-opts input-opts
@@ -825,6 +827,10 @@
(when-not add-tag-property?
(log/error :msg "No :db/id found or created for chosen" :chosen chosen)))))})
(= :block/tags (:db/ident property))
(assoc :exact-match-exclude-items
(set (map (fn [ident] (:block/title (db/entity ident))) ldb/private-tags)))
(and (seq classes') (not tags-or-alias?))
(assoc
;; Provides additional completion for inline classes on new pages or objects