fix: disallow built-in class properties to be deleted

fixes LOG-3050
pull/11102/head
Tienson Qin 2024-03-06 22:07:09 +08:00
parent fbce74522b
commit 61bb5ed862
3 changed files with 72 additions and 60 deletions

View File

@ -9,7 +9,8 @@
[logseq.db.frontend.content :as db-content]
[clojure.set :as set]
[logseq.db.frontend.rules :as rules]
[logseq.db.frontend.entity-plus]))
[logseq.db.frontend.entity-plus]
[logseq.db.frontend.class :as db-class]))
;; Use it as an input argument for datalog queries
(def block-attrs
@ -553,6 +554,17 @@
[entity]
(:built-in? (:block/metadata entity)))
(defn built-in-class-property?
"Whether property a built-in property for the specific class"
[class-entity property-entity]
(let [class-properties (some (fn [[_k v]]
(when (= (:original-name v) (:block/original-name class-entity))
(set (get-in v [:schema :properties]))))
db-class/built-in-classes)]
(and (built-in? class-entity)
(built-in? property-entity)
(contains? class-properties (:block/name property-entity)))))
(comment
(defn db-based-graph?
"Whether the current graph is db-only"

View File

@ -158,7 +158,7 @@
built-in-property? (contains? db-property/built-in-properties-keys-str (:block/original-name property))
property (db/sub-block (:db/id property))
built-in? (ldb/built-in? property)
disabled? (or built-in-property? config/publishing?)
disabled? (or built-in? config/publishing?)
hide-delete? (or (= (:db/id block) (:db/id property)) ; property page
add-new-property?)
class? (contains? (:block/type block) "class")
@ -171,18 +171,16 @@
[:div.grid.gap-2.p-1
[:div.grid.grid-cols-4.gap-1.items-center.leading-8
[:label.col-span-1 "Name:"]
(if built-in?
[:div.col-span-2 (:block/original-name property)]
(shui/input
{:class "col-span-2 !px-2 !py-0 !h-8"
:auto-focus (not add-new-property?)
:on-change #(reset! *property-name (util/evalue %))
:on-blur save-property-fn
:on-key-press (fn [e]
(when (= "Enter" (util/ekey e))
(save-property-fn)))
:disabled disabled?
:default-value @*property-name}))]
(shui/input
{:class "col-span-2 !px-2 !py-0 !h-8"
:auto-focus (not add-new-property?)
:on-change #(reset! *property-name (util/evalue %))
:on-blur save-property-fn
:on-key-press (fn [e]
(when (= "Enter" (util/ekey e))
(save-property-fn)))
:disabled disabled?
:default-value @*property-name})]
[:div.grid.grid-cols-4.gap-1.items-center.leading-8
[:label.col-span-1 "Icon:"]
@ -357,7 +355,7 @@
:disabled disabled?
:default-value (:description @*property-schema)})])]]
(when-not hide-delete?
(when-not (or hide-delete? (ldb/built-in-class-property? block property))
(shui/button
{:variant :secondary
:class "mt-4 hover:text-red-700"
@ -553,20 +551,21 @@
:on-context-menu (fn [^js e]
(util/stop e)
(shui/popup-show! e
[(shui/dropdown-menu-item
{:on-click (fn []
(when-let [schema (some-> property :block/schema)]
(components-pu/update-property! property property-name (assoc schema :hide? true))
(shui/popup-hide!)))}
"Hide property")
(shui/dropdown-menu-item
{:on-click (fn []
(handle-delete-property! block property {:class-schema? class-schema?})
(shui/popup-hide!))}
[:span.w-full.text-red-rx-07.hover:text-red-rx-09
"Delete property"])]
{:as-menu? true
:content-props {:class "w-48"}}))}
[(shui/dropdown-menu-item
{:on-click (fn []
(when-let [schema (some-> property :block/schema)]
(components-pu/update-property! property property-name (assoc schema :hide? true))
(shui/popup-hide!)))}
"Hide property")
(when-not (ldb/built-in-class-property? block property)
(shui/dropdown-menu-item
{:on-click (fn []
(handle-delete-property! block property {:class-schema? class-schema?})
(shui/popup-hide!))}
[:span.w-full.text-red-rx-07.hover:text-red-rx-09
"Delete property"]))]
{:as-menu? true
:content-props {:class "w-48"}}))}
(when block?
[:a.block-control
{:on-click (fn [event]
@ -582,14 +581,14 @@
;; icon picker
(let [content-fn (fn [{:keys [id]}]
(icon-component/icon-search
{:on-chosen
(fn [_e icon]
(let [icon-property-id (db-pu/get-built-in-property-uuid :icon)]
(when icon
(p/let [_ (db-property-handler/<update-property! repo
(:block/uuid property)
{:properties {icon-property-id icon}})]
(shui/popup-hide! id)))))}))]
{:on-chosen
(fn [_e icon]
(let [icon-property-id (db-pu/get-built-in-property-uuid :icon)]
(when icon
(p/let [_ (db-property-handler/<update-property! repo
(:block/uuid property)
{:properties {icon-property-id icon}})]
(shui/popup-hide! id)))))}))]
[:button.flex
{:on-click #(shui/popup-show! (.-target %) content-fn {:as-menu? true})}
(if icon
@ -611,21 +610,21 @@
(.preventDefault e)))
:on-click (fn [^js e]
(shui/popup-show!
(.-target e)
(fn [{:keys [id]}]
[:div.p-2
[:h2.text-lg.font-medium.mb-2.p-1 "Configure property"]
(property-config block property
{:inline-text inline-text
:page-cp page-cp
:class-schema? class-schema?
:toggle-fn #(shui/popup-hide! id)})])
{:content-props {:class "property-configure-popup-content"
:collisionPadding {:bottom 10 :top 10}
:avoidCollisions true
:align "start"}
:auto-side? true
:as-menu? true}))}
(.-target e)
(fn [{:keys [id]}]
[:div.p-2
[:h2.text-lg.font-medium.mb-2.p-1 "Configure property"]
(property-config block property
{:inline-text inline-text
:page-cp page-cp
:class-schema? class-schema?
:toggle-fn #(shui/popup-hide! id)})])
{:content-props {:class "property-configure-popup-content"
:collisionPadding {:bottom 10 :top 10}
:avoidCollisions true
:align "start"}
:auto-side? true
:as-menu? true}))}
[:div {:style {:padding-left 6}} (:block/original-name property)]])]))
(defn- resolve-linked-block-if-exists

View File

@ -355,14 +355,15 @@
[repo class-uuid k-uuid]
(when-let [class (db/entity repo [:block/uuid class-uuid])]
(when (contains? (:block/type class) "class")
(when-let [property (db/pull repo '[*] [:block/uuid k-uuid])]
(let [property-uuid (:block/uuid property)
{:keys [properties] :as class-schema} (:block/schema class)
new-properties (vec (distinct (remove #{property-uuid} properties)))
class-new-schema (assoc class-schema :properties new-properties)]
(db/transact! repo [{:db/id (:db/id class)
:block/schema class-new-schema}]
{:outliner-op :save-block}))))))
(when-let [property (db/entity repo [:block/uuid k-uuid])]
(when-not (ldb/built-in-class-property? class property)
(let [property-uuid (:block/uuid property)
{:keys [properties] :as class-schema} (:block/schema class)
new-properties (vec (distinct (remove #{property-uuid} properties)))
class-new-schema (assoc class-schema :properties new-properties)]
(db/transact! repo [{:db/id (:db/id class)
:block/schema class-new-schema}]
{:outliner-op :save-block})))))))
(defn class-set-schema!
[repo class-uuid schema]