diff --git a/clj-e2e/test/logseq/e2e/plugins_basic_test.clj b/clj-e2e/test/logseq/e2e/plugins_basic_test.clj index b5a65477b5..831f5fed05 100644 --- a/clj-e2e/test/logseq/e2e/plugins_basic_test.clj +++ b/clj-e2e/test/logseq/e2e/plugins_basic_test.clj @@ -289,7 +289,7 @@ (deftest get-all-properties-test (testing "get_all_properties" (let [result (ls-api-call! :editor.get_all_properties)] - (is (>= (count result) 94))))) + (is (>= (count result) 20))))) (deftest get-tag-objects-test (testing "get_tag_objects" @@ -387,4 +387,4 @@ _ (ls-api-call! :editor.setPropertyNodeTags property-name tags) property (ls-api-call! :editor.getProperty property-name) node-tags (get property ":logseq.property/classes")] - (is (= (set node-tags) (set tags)) "property node tags should match the set tags")))) \ No newline at end of file + (is (= (set node-tags) (set tags)) "property node tags should match the set tags")))) diff --git a/deps/outliner/src/logseq/outliner/op.cljs b/deps/outliner/src/logseq/outliner/op.cljs index d78d545285..62e7a37ff3 100644 --- a/deps/outliner/src/logseq/outliner/op.cljs +++ b/deps/outliner/src/logseq/outliner/op.cljs @@ -299,18 +299,26 @@ (defn apply-ops! [conn ops opts] (assert (ops-validator ops) ops) - (let [single-op-outliner-op (when (= 1 (count ops)) - (first (first ops))) - opts' (cond-> (assoc opts - :transact-opts {:conn conn} - :local-tx? true) - (and single-op-outliner-op - (nil? (:outliner-op opts))) - (assoc :outliner-op single-op-outliner-op)) - *result (atom nil)] - (outliner-tx/transact! - opts' - (doseq [op-entry ops] - (apply-op! conn opts' *result op-entry))) - - @*result)) + (letfn [(apply-ops-batch! + [ops'] + (let [single-op-outliner-op (when (= 1 (count ops')) + (first (first ops'))) + opts' (cond-> (assoc opts + :transact-opts {:conn conn} + :local-tx? true) + (and single-op-outliner-op + (nil? (:outliner-op opts))) + (assoc :outliner-op single-op-outliner-op)) + *result (atom nil)] + (outliner-tx/transact! + opts' + (doseq [op-entry ops'] + (apply-op! conn opts' *result op-entry))) + @*result))] + (let [schema-ops (filter #(= :upsert-property (first %)) ops) + data-ops (remove #(= :upsert-property (first %)) ops) + schema-result (when (seq schema-ops) + (apply-ops-batch! schema-ops))] + (if (seq data-ops) + (apply-ops-batch! data-ops) + schema-result)))) diff --git a/deps/outliner/test/logseq/outliner/op_test.cljs b/deps/outliner/test/logseq/outliner/op_test.cljs index cba76e68da..f4e53d23e2 100644 --- a/deps/outliner/test/logseq/outliner/op_test.cljs +++ b/deps/outliner/test/logseq/outliner/op_test.cljs @@ -3,7 +3,8 @@ [datascript.core :as d] [logseq.db :as ldb] [logseq.db.test.helper :as db-test] - [logseq.outliner.op :as outliner-op])) + [logseq.outliner.op :as outliner-op] + [logseq.outliner.property :as outliner-property])) (deftest toggle-reaction-op (testing "toggles reactions via outliner ops" @@ -38,3 +39,80 @@ {}) (let [block-entity (d/entity @conn [:block/uuid target-uuid])] (is (empty? (:logseq.property.reaction/_target block-entity)))))))) + +(deftest apply-ops-plugin-property-sequence-test + (testing "plugin property ops remain visible after a single apply-ops! batch" + (let [conn (db-test/create-conn-with-blocks + [{:page {:block/title "Test"} + :blocks [{:block/title "Block"}]}]) + block (db-test/find-block-by-content @conn "Block") + block-id (:db/id block)] + (outliner-op/apply-ops! + conn + [[:upsert-property [:plugin.property._test_plugin/x1 {:logseq.property/type :checkbox + :db/cardinality :db.cardinality/one} + {:property-name :x1}]] + [:set-block-property [block-id :plugin.property._test_plugin/x1 true]] + [:upsert-property [:plugin.property._test_plugin/x2 {:logseq.property/type :url + :db/cardinality :db.cardinality/one} + {:property-name :x2}]] + [:set-block-property [block-id :plugin.property._test_plugin/x2 "https://logseq.com"]] + [:upsert-property [:plugin.property._test_plugin/x3 {:logseq.property/type :number + :db/cardinality :db.cardinality/one} + {:property-name :x3}]] + [:set-block-property [block-id :plugin.property._test_plugin/x3 1]] + [:upsert-property [:plugin.property._test_plugin/x4 {:logseq.property/type :number + :db/cardinality :db.cardinality/many} + {:property-name :x4}]] + [:set-block-property [block-id :plugin.property._test_plugin/x4 1]] + [:upsert-property [:plugin.property._test_plugin/x5 {:logseq.property/type :json + :db/cardinality :db.cardinality/one} + {:property-name :x5}]] + [:set-block-property [block-id :plugin.property._test_plugin/x5 "{\"foo\":\"bar\"}"]] + [:upsert-property [:plugin.property._test_plugin/x6 {:logseq.property/type :page + :db/cardinality :db.cardinality/one} + {:property-name :x6}]] + [:set-block-property [block-id :plugin.property._test_plugin/x6 "Page x"]] + [:upsert-property [:plugin.property._test_plugin/x7 {:logseq.property/type :page + :db/cardinality :db.cardinality/many} + {:property-name :x7}]] + [:set-block-property [block-id :plugin.property._test_plugin/x7 "Page y"]] + [:set-block-property [block-id :plugin.property._test_plugin/x7 "Page z"]] + [:upsert-property [:plugin.property._test_plugin/x8 {:logseq.property/type :default + :db/cardinality :db.cardinality/one} + {:property-name :x8}]] + [:set-block-property [block-id :plugin.property._test_plugin/x8 "some content"]]] + {}) + (let [block' (d/entity @conn block-id)] + (is (true? (:plugin.property._test_plugin/x1 block'))) + (is (= "https://logseq.com" + (:block/title (:plugin.property._test_plugin/x2 block')))) + (is (= 1 + (:logseq.property/value (:plugin.property._test_plugin/x3 block')))) + (is (= #{1} + (set (map :logseq.property/value (:plugin.property._test_plugin/x4 block'))))) + (is (= "{\"foo\":\"bar\"}" (:plugin.property._test_plugin/x5 block'))) + (is (= "page x" + (:block/name (:plugin.property._test_plugin/x6 block')))) + (is (= #{"page y" "page z"} + (set (map :block/name (:plugin.property._test_plugin/x7 block'))))) + (is (= "some content" + (:block/title (:plugin.property._test_plugin/x8 block')))))))) + +(deftest direct-plugin-many-page-property-appends-values-test + (testing "direct property operations keep both page values" + (let [conn (db-test/create-conn-with-blocks + [{:page {:block/title "Test"} + :blocks [{:block/title "Block"}]}]) + block (db-test/find-block-by-content @conn "Block") + block-id (:db/id block) + property-id :plugin.property._test_plugin/x7] + (outliner-property/upsert-property! conn property-id + {:logseq.property/type :page + :db/cardinality :db.cardinality/many} + {:property-name :x7}) + (outliner-property/set-block-property! conn block-id property-id "Page y") + (outliner-property/set-block-property! conn block-id property-id "Page z") + (is (= #{"page y" "page z"} + (set (map :block/name + (:plugin.property._test_plugin/x7 (d/entity @conn block-id)))))))))