Parcourir la source

Merge branch 'master' into refactor/separate-og-and-db-version

Tienson Qin il y a 1 jour
Parent
commit
c9a92f92be

+ 68 - 0
clj-e2e/test/logseq/e2e/plugins_basic_test.clj

@@ -335,3 +335,71 @@
           result (ls-api-call! :editor.get_tag_objects "logseq.class/Task")]
           result (ls-api-call! :editor.get_tag_objects "logseq.class/Task")]
       (is (= (count result) 1))
       (is (= (count result) 1))
       (is (= "task 1" (get (first result) "title"))))))
       (is (= "task 1" (get (first result) "title"))))))
+
+(deftest create-and-get-tag-test
+  (testing "create and get tag with title or ident"
+    (let [title "book1"
+          title-ident (str :plugin.class._test_plugin/book1)
+          tag1 (ls-api-call! :editor.createTag title)
+          tag2 (ls-api-call! :editor.getTag title)
+          tag3 (ls-api-call! :editor.getTag title-ident)
+          tag4 (ls-api-call! :editor.getTag (get tag1 "uuid"))]
+      (is (= (get tag1 "ident") title-ident) "create tag with title from test as plugin")
+      (is (= (get tag2 "ident") title-ident) "get tag with title")
+      (is (= (get tag3 "title") title) "get tag with ident")
+      (is (= (get tag4 "title") title) "get tag with uuid")))
+
+  (testing "add and remove tag extends"
+    (let [tag1 (ls-api-call! :editor.createTag "tag1")
+          tag2 (ls-api-call! :editor.createTag "tag2")
+          tag3 (ls-api-call! :editor.createTag "tag3")
+          id1 (get tag1 "id")
+          id2 (get tag2 "id")
+          id3 (get tag3 "id")
+          _ (ls-api-call! :editor.addTagExtends id1 id2)
+          tag1 (ls-api-call! :editor.getTag id1)]
+      (is (= (get tag1 ":logseq.property.class/extends") [id2]) "tag1 extends tag2 with db id")
+      (let [_ (ls-api-call! :editor.addTagExtends id1 id3)
+            tag1 (ls-api-call! :editor.getTag id1)]
+        (is (= (get tag1 ":logseq.property.class/extends") [id2 id3]) "tag1 extends tag2,tag3 with db ids")))))
+
+(deftest get-tags-by-name-test
+  (testing "get tags by exact name"
+    (let [tag-name "product"
+          tag1 (ls-api-call! :editor.createTag tag-name)
+          result (ls-api-call! :editor.getTagsByName tag-name)]
+      (is (= 1 (count result)) "should return exactly one tag")
+      (is (= (get tag1 "uuid") (get (first result) "uuid")) "should return the created tag")
+      (is (= (get tag1 "title") (get (first result) "title")) "tag title should match")))
+
+  (testing "get tags by name is case-insensitive"
+    (let [tag-name "TestTag123"
+          _ (ls-api-call! :editor.createTag tag-name)
+          result-lower (ls-api-call! :editor.getTagsByName "testtag123")
+          result-upper (ls-api-call! :editor.getTagsByName "TESTTAG123")
+          result-mixed (ls-api-call! :editor.getTagsByName "TeStTaG123")]
+      (is (= 1 (count result-lower)) "should find tag with lowercase search")
+      (is (= 1 (count result-upper)) "should find tag with uppercase search")
+      (is (= 1 (count result-mixed)) "should find tag with mixed case search")
+      (is (= (get (first result-lower) "uuid") (get (first result-upper) "uuid")) "all searches should return same tag")
+      (is (= (get (first result-lower) "uuid") (get (first result-mixed) "uuid")) "all searches should return same tag")))
+
+  (testing "get tags by name returns empty array for non-existent tag"
+    (let [result (ls-api-call! :editor.getTagsByName "NonExistentTag12345")]
+      (is (empty? result) "should return empty array for non-existent tag")))
+
+  (testing "get tags by name filters out non-tag pages"
+    (let [page-name "regular-page"
+          _ (page/new-page page-name)
+          result (ls-api-call! :editor.getTagsByName page-name)]
+      (is (empty? result) "should not return regular pages, only tags")))
+
+  (testing "get tags by name with multiple tags having similar names"
+    (let [tag1 (ls-api-call! :editor.createTag "category")
+          tag2 (ls-api-call! :editor.createTag "Category")
+          result (ls-api-call! :editor.getTagsByName "category")]
+      ;; Due to case-insensitive name normalization, both tags should be the same
+      (is (>= (count result) 1) "should return at least one tag")
+      ;; Verify the result contains valid tag structure
+      (is (string? (get (first result) "uuid")) "returned tag should have uuid")
+      (is (string? (get (first result) "title")) "returned tag should have title"))))

+ 27 - 17
deps/outliner/src/logseq/outliner/page.cljs

@@ -247,6 +247,7 @@
                (map (fn [id] (d/entity db [:block/uuid id])) tags)
                (map (fn [id] (d/entity db [:block/uuid id])) tags)
                tags)
                tags)
         class? (or class? (some (fn [t] (= :logseq.class/Tag (:db/ident t))) tags))
         class? (or class? (some (fn [t] (= :logseq.class/Tag (:db/ident t))) tags))
+        class-ident-namespace? (and class? class-ident-namespace (string? class-ident-namespace))
         title (sanitize-title title*)
         title (sanitize-title title*)
         types (cond class?
         types (cond class?
                     #{:logseq.class/Tag}
                     #{:logseq.class/Tag}
@@ -258,29 +259,38 @@
                     (set (map :db/ident tags))
                     (set (map :db/ident tags))
                     :else
                     :else
                     #{:logseq.class/Page})
                     #{:logseq.class/Page})
-        existing-page-id (first (ldb/page-exists? db title types))
+        existing-names-page (ldb/page-exists? db title types)
+        existing-page-id (some->> existing-names-page
+                                  (filter #(try (when-let [e (and class-ident-namespace? (d/entity db %))]
+                                                  (let [ns' (namespace (:db/ident e))]
+                                                    (= (str ns') class-ident-namespace)))
+                                                (catch :default _ false)))
+                                  (first))
         existing-page (some->> existing-page-id (d/entity db))]
         existing-page (some->> existing-page-id (d/entity db))]
     (if (and existing-page (not (:block/parent existing-page)))
     (if (and existing-page (not (:block/parent existing-page)))
       (let [tx-meta {:persist-op? persist-op?
       (let [tx-meta {:persist-op? persist-op?
                      :outliner-op :save-block}]
                      :outliner-op :save-block}]
-        (when (and class?
-                   (not (ldb/class? existing-page))
-                   (ldb/internal-page? existing-page))
+        (if (and class?
+                 (not (ldb/class? existing-page))
+                 (ldb/internal-page? existing-page))
           ;; Convert existing page to class
           ;; Convert existing page to class
           (let [tx-data [(merge (db-class/build-new-class db
           (let [tx-data [(merge (db-class/build-new-class db
                                                           (select-keys existing-page [:block/title :block/uuid :block/created-at])
                                                           (select-keys existing-page [:block/title :block/uuid :block/created-at])
-                                                          (when (and class? class-ident-namespace (string? class-ident-namespace))
+                                                          (when class-ident-namespace?
                                                             {:ident-namespace class-ident-namespace}))
                                                             {:ident-namespace class-ident-namespace}))
                                 (select-keys existing-page [:db/ident]))
                                 (select-keys existing-page [:db/ident]))
                          [:db/retract [:block/uuid (:block/uuid existing-page)] :block/tags :logseq.class/Page]]]
                          [:db/retract [:block/uuid (:block/uuid existing-page)] :block/tags :logseq.class/Page]]]
             {:tx-meta tx-meta
             {:tx-meta tx-meta
              :tx-data tx-data
              :tx-data tx-data
              :page-uuid (:block/uuid existing-page)
              :page-uuid (:block/uuid existing-page)
-             :title (:block/title existing-page)})))
-      (let [page           (gp-block/page-name->map title db true date-formatter
-                                                    {:class? class?
-                                                     :page-uuid (when (uuid? uuid') uuid')
-                                                     :skip-existing-page-check? true})
+             :title (:block/title existing-page)})
+          ;; Just return existing page info
+          {:page-uuid (:block/uuid existing-page)
+           :title (:block/title existing-page)}))
+      (let [page (gp-block/page-name->map title db true date-formatter
+                                          {:class? class?
+                                           :page-uuid (when (uuid? uuid') uuid')
+                                           :skip-existing-page-check? true})
             [page parents'] (if (and (text/namespace-page? title) split-namespace?)
             [page parents'] (if (and (text/namespace-page? title) split-namespace?)
                               (let [pages (split-namespace-pages db page date-formatter class?)]
                               (let [pages (split-namespace-pages db page date-formatter class?)]
                                 [(last pages) (butlast pages)])
                                 [(last pages) (butlast pages)])
@@ -296,11 +306,11 @@
               (outliner-validate/validate-page-title-characters (str (:block/title parent)) {:node parent})))
               (outliner-validate/validate-page-title-characters (str (:block/title parent)) {:node parent})))
 
 
           (let [page-uuid (:block/uuid page)
           (let [page-uuid (:block/uuid page)
-                page-txs  (build-page-tx db properties page (select-keys options [:whiteboard? :class? :tags :class-ident-namespace]))
-                txs      (concat
-                          ;; transact doesn't support entities
-                          (remove de/entity? parents')
-                          page-txs)
+                page-txs (build-page-tx db properties page (select-keys options [:whiteboard? :class? :tags :class-ident-namespace]))
+                txs (concat
+                     ;; transact doesn't support entities
+                     (remove de/entity? parents')
+                     page-txs)
                 tx-meta (cond-> {:persist-op? persist-op?
                 tx-meta (cond-> {:persist-op? persist-op?
                                  :outliner-op :create-page}
                                  :outliner-op :create-page}
                           today-journal?
                           today-journal?
@@ -315,5 +325,5 @@
   [conn title opts]
   [conn title opts]
   (let [{:keys [tx-meta tx-data title' page-uuid]} (create @conn title opts)]
   (let [{:keys [tx-meta tx-data title' page-uuid]} (create @conn title opts)]
     (when (seq tx-data)
     (when (seq tx-data)
-      (ldb/transact! conn tx-data tx-meta)
-      [title' page-uuid])))
+      (ldb/transact! conn tx-data tx-meta))
+    [title' page-uuid]))

+ 3 - 3
libs/package.json

@@ -14,8 +14,8 @@
     "build": "tsc && rm dist/*.js && npm run build:user",
     "build": "tsc && rm dist/*.js && npm run build:user",
     "lint": "prettier --check \"src/**/*.{ts, js}\"",
     "lint": "prettier --check \"src/**/*.{ts, js}\"",
     "fix": "prettier --write \"src/**/*.{ts, js}\"",
     "fix": "prettier --write \"src/**/*.{ts, js}\"",
-    "build:docs": "typedoc src/LSPlugin.user.ts",
-    "build:docs:json": "typedoc --plugin typedoc-plugin-lsp-docs src/LSPlugin.user.ts && typedoc --json docs/out.json ./src/LSPlugin.user.ts"
+    "build:docs": "typedoc --plugin typedoc-plugin-lsp-docs src/LSPlugin.user.ts",
+    "build:docs:json": "typedoc --json docs/out.json ./src/LSPlugin.user.ts"
   },
   },
   "dependencies": {
   "dependencies": {
     "csstype": "3.1.0",
     "csstype": "3.1.0",
@@ -41,7 +41,7 @@
     "terser-webpack-plugin": "^5.3.6",
     "terser-webpack-plugin": "^5.3.6",
     "ts-loader": "9.3.0",
     "ts-loader": "9.3.0",
     "typedoc": "0.28.15",
     "typedoc": "0.28.15",
-    "typedoc-plugin-lsp-docs": "^0.0.1",
+    "typedoc-plugin-lsp-docs": "^0.0.2",
     "typescript": "5.9.3",
     "typescript": "5.9.3",
     "webpack": "5.94.0",
     "webpack": "5.94.0",
     "webpack-bundle-analyzer": "4.5.0",
     "webpack-bundle-analyzer": "4.5.0",

+ 14 - 26
libs/src/LSPlugin.ts

@@ -697,15 +697,13 @@ export interface IEditorProxy extends Record<string, any> {
    * @param opts
    * @param opts
    */
    */
   insertBlock: (
   insertBlock: (
-    srcBlock: BlockIdentity,
+    srcBlock: BlockIdentity | EntityID,
     content: string,
     content: string,
     opts?: Partial<{
     opts?: Partial<{
       before: boolean
       before: boolean
       sibling: boolean
       sibling: boolean
       start: boolean
       start: boolean
       end: boolean
       end: boolean
-      isPageBlock: boolean
-      focus: boolean
       customUUID: string
       customUUID: string
       properties: {}
       properties: {}
     }>
     }>
@@ -723,30 +721,20 @@ export interface IEditorProxy extends Record<string, any> {
   ) => Promise<Array<BlockEntity> | null>
   ) => Promise<Array<BlockEntity> | null>
 
 
   updateBlock: (
   updateBlock: (
-    srcBlock: BlockIdentity,
+    srcBlock: BlockIdentity | EntityID,
     content: string,
     content: string,
     opts?: Partial<{ properties: {} }>
     opts?: Partial<{ properties: {} }>
   ) => Promise<void>
   ) => Promise<void>
 
 
-  removeBlock: (srcBlock: BlockIdentity) => Promise<void>
+  removeBlock: (srcBlock: BlockIdentity | EntityID) => Promise<void>
 
 
   getBlock: (
   getBlock: (
     srcBlock: BlockIdentity | EntityID,
     srcBlock: BlockIdentity | EntityID,
     opts?: Partial<{ includeChildren: boolean }>
     opts?: Partial<{ includeChildren: boolean }>
   ) => Promise<BlockEntity | null>
   ) => Promise<BlockEntity | null>
 
 
-  /**
-   * @example
-   *
-   * ```ts
-   *  logseq.Editor.setBlockCollapsed('uuid', true)
-   *  logseq.Editor.setBlockCollapsed('uuid', 'toggle')
-   * ```
-   * @param uuid
-   * @param opts
-   */
   setBlockCollapsed: (
   setBlockCollapsed: (
-    uuid: BlockUUID,
+    srcBlock: BlockIdentity | EntityID,
     opts: { flag: boolean | 'toggle' } | boolean | 'toggle'
     opts: { flag: boolean | 'toggle' } | boolean | 'toggle'
   ) => Promise<void>
   ) => Promise<void>
 
 
@@ -780,7 +768,8 @@ export interface IEditorProxy extends Record<string, any> {
   getAllProperties: () => Promise<PageEntity[] | null>
   getAllProperties: () => Promise<PageEntity[] | null>
   getTagObjects: (nameOrIdent: string) => Promise<BlockEntity[] | null>
   getTagObjects: (nameOrIdent: string) => Promise<BlockEntity[] | null>
   createTag: (tagName: string, opts?: Partial<{ uuid: string }>) => Promise<PageEntity | null>
   createTag: (tagName: string, opts?: Partial<{ uuid: string }>) => Promise<PageEntity | null>
-  getTag: (nameOrIdent: string) => Promise<PageEntity | null>
+  getTag: (nameOrIdent: string | EntityID) => Promise<PageEntity | null>
+  getTagsByName: (tagName: string) => Promise<Array<PageEntity> | null>
   addTagProperty: (tagId: BlockIdentity, propertyIdOrName: BlockIdentity) => Promise<void>
   addTagProperty: (tagId: BlockIdentity, propertyIdOrName: BlockIdentity) => Promise<void>
   removeTagProperty: (tagId: BlockIdentity, propertyIdOrName: BlockIdentity) => Promise<void>
   removeTagProperty: (tagId: BlockIdentity, propertyIdOrName: BlockIdentity) => Promise<void>
   addTagExtends: (tagId: BlockIdentity, parentTagIdOrName: BlockIdentity) => Promise<void>
   addTagExtends: (tagId: BlockIdentity, parentTagIdOrName: BlockIdentity) => Promise<void>
@@ -806,11 +795,11 @@ export interface IEditorProxy extends Record<string, any> {
   ) => Promise<BlockEntity | null>
   ) => Promise<BlockEntity | null>
 
 
   getPreviousSiblingBlock: (
   getPreviousSiblingBlock: (
-    srcBlock: BlockIdentity
+    srcBlock: BlockIdentity | EntityID
   ) => Promise<BlockEntity | null>
   ) => Promise<BlockEntity | null>
 
 
   getNextSiblingBlock: (
   getNextSiblingBlock: (
-    srcBlock: BlockIdentity
+    srcBlock: BlockIdentity | EntityID
   ) => Promise<BlockEntity | null>
   ) => Promise<BlockEntity | null>
 
 
   moveBlock: (
   moveBlock: (
@@ -843,17 +832,15 @@ export interface IEditorProxy extends Record<string, any> {
 
 
   // block property related APIs
   // block property related APIs
   upsertBlockProperty: (
   upsertBlockProperty: (
-    block: BlockIdentity,
+    block: BlockIdentity | EntityID,
     key: string,
     key: string,
     value: any
     value: any
   ) => Promise<void>
   ) => Promise<void>
 
 
-  removeBlockProperty: (block: BlockIdentity, key: string) => Promise<void>
-
-  getBlockProperty: (block: BlockIdentity, key: string) => Promise<BlockEntity | unknown>
-
-  getBlockProperties: (block: BlockIdentity) => Promise<Record<string, any> | null>
-  getPageProperties: (page: PageIdentity) => Promise<Record<string, any> | null>
+  removeBlockProperty: (block: BlockIdentity | EntityID, key: string) => Promise<void>
+  getBlockProperty: (block: BlockIdentity | EntityID, key: string) => Promise<BlockEntity | null>
+  getBlockProperties: (block: BlockIdentity | EntityID) => Promise<Record<string, any> | null>
+  getPageProperties: (page: PageIdentity | EntityID) => Promise<Record<string, any> | null>
 
 
   scrollToBlockInPage: (
   scrollToBlockInPage: (
     pageName: BlockPageName,
     pageName: BlockPageName,
@@ -862,6 +849,7 @@ export interface IEditorProxy extends Record<string, any> {
   ) => void
   ) => void
 
 
   openInRightSidebar: (id: BlockUUID | EntityID) => void
   openInRightSidebar: (id: BlockUUID | EntityID) => void
+  openPDFViewer: (assetBlockIdOrFileUrl: string | EntityID) => Promise<void>
 
 
   /**
   /**
    * @example https://github.com/logseq/logseq-plugin-samples/tree/master/logseq-a-translator
    * @example https://github.com/logseq/logseq-plugin-samples/tree/master/logseq-a-translator

+ 8 - 0
src/main/frontend/components/property/value.cljs

@@ -1279,6 +1279,13 @@
      (fn []
      (fn []
        #(set-property-value! @*value))
        #(set-property-value! @*value))
      [])
      [])
+
+    (hooks/use-effect!
+     (fn []
+       (set-value! number-value)
+       #())
+     [number-value])
+
     [:div.ls-number.flex.flex-1.jtrigger
     [:div.ls-number.flex.flex-1.jtrigger
      {:ref *ref
      {:ref *ref
       :on-click #(do
       :on-click #(do
@@ -1291,6 +1298,7 @@
          :class (str "ls-number-input h-6 px-0 py-0 border-none bg-transparent focus-visible:ring-0 focus-visible:ring-offset-0 text-base"
          :class (str "ls-number-input h-6 px-0 py-0 border-none bg-transparent focus-visible:ring-0 focus-visible:ring-offset-0 text-base"
                      (when table-view? " text-sm"))
                      (when table-view? " text-sm"))
          :value value
          :value value
+         :type "number"
          :on-change (fn [e]
          :on-change (fn [e]
                       (set-value! (util/evalue e))
                       (set-value! (util/evalue e))
                       (reset! *value (util/evalue e)))
                       (reset! *value (util/evalue e)))

+ 4 - 3
src/main/frontend/handler/editor.cljs

@@ -3327,10 +3327,11 @@
 
 
 (defn toggle-open-block-children! [block-id]
 (defn toggle-open-block-children! [block-id]
   (p/let [blocks (<all-blocks-with-level {:incremental? false
   (p/let [blocks (<all-blocks-with-level {:incremental? false
-                                          :collapse? true
+                                          :expanded? true
                                           :root-block block-id})
                                           :root-block block-id})
-          all-expanded? (empty? blocks)]
-    (if all-expanded?
+          children-blocks (remove #(= block-id (:block/uuid %)) blocks)
+          any-expanded? (seq (filter (complement util/collapsed?) children-blocks))]
+    (if any-expanded?
       (collapse-all! block-id {:collapse-self? false})
       (collapse-all! block-id {:collapse-self? false})
       (expand-all! block-id))))
       (expand-all! block-id))))
 
 

+ 2 - 0
src/main/logseq/api.cljs

@@ -132,6 +132,7 @@
 (def ^:export set_block_collapsed api-editor/set_block_collapsed)
 (def ^:export set_block_collapsed api-editor/set_block_collapsed)
 (def ^:export update_block api-editor/update_block)
 (def ^:export update_block api-editor/update_block)
 (def ^:export upsert_block_property api-editor/upsert_block_property)
 (def ^:export upsert_block_property api-editor/upsert_block_property)
+(def ^:export open_pdf_viewer api-editor/open_pdf_viewer)
 
 
 ;; ui
 ;; ui
 (def ^:export show_msg sdk-ui/-show_msg)
 (def ^:export show_msg sdk-ui/-show_msg)
@@ -200,6 +201,7 @@
 (def ^:export get_tag_objects db-based-api/get-tag-objects)
 (def ^:export get_tag_objects db-based-api/get-tag-objects)
 (def ^:export create_tag db-based-api/create-tag)
 (def ^:export create_tag db-based-api/create-tag)
 (def ^:export get_tag db-based-api/get-tag)
 (def ^:export get_tag db-based-api/get-tag)
+(def ^:export get_tags_by_name db-based-api/get-tags-by-name)
 (def ^:export add_tag_extends db-based-api/add-tag-extends)
 (def ^:export add_tag_extends db-based-api/add-tag-extends)
 (def ^:export remove_tag_extends db-based-api/remove-tag-extends)
 (def ^:export remove_tag_extends db-based-api/remove-tag-extends)
 (def ^:export add_block_tag db-based-api/add-block-tag)
 (def ^:export add_block_tag db-based-api/add-block-tag)

+ 28 - 16
src/main/logseq/api/db_based.cljs

@@ -8,6 +8,7 @@
             [datascript.core :as d]
             [datascript.core :as d]
             [frontend.db :as db]
             [frontend.db :as db]
             [frontend.db.async :as db-async]
             [frontend.db.async :as db-async]
+            [frontend.db.conn :as db-conn]
             [frontend.db.model :as db-model]
             [frontend.db.model :as db-model]
             [frontend.handler.common.page :as page-common-handler]
             [frontend.handler.common.page :as page-common-handler]
             [frontend.handler.db-based.page :as db-page-handler]
             [frontend.handler.db-based.page :as db-page-handler]
@@ -21,6 +22,7 @@
             [logseq.api.block :as api-block]
             [logseq.api.block :as api-block]
             [logseq.db :as ldb]
             [logseq.db :as ldb]
             [logseq.db.common.entity-util :as common-entity-util]
             [logseq.db.common.entity-util :as common-entity-util]
+            [logseq.db.frontend.entity-util :as entity-util]
             [logseq.graph-parser.text :as text]
             [logseq.graph-parser.text :as text]
             [logseq.outliner.core :as outliner-core]
             [logseq.outliner.core :as outliner-core]
             [logseq.sdk.core]
             [logseq.sdk.core]
@@ -219,9 +221,12 @@
    (when (text/namespace-page? title)
    (when (text/namespace-page? title)
      (throw (ex-info "Tag title shouldn't include forward slash" {:title title})))
      (throw (ex-info "Tag title shouldn't include forward slash" {:title title})))
    (let [opts (bean/->clj opts)
    (let [opts (bean/->clj opts)
+         custom-ident-namespace (:customIdentNamespace opts)
+         class-ident-namespace (or (some-> custom-ident-namespace (api-block/sanitize-user-property-name))
+                                   (api-block/resolve-class-prefix-for-db this))
          opts' (assoc opts
          opts' (assoc opts
                       :redirect? false
                       :redirect? false
-                      :class-ident-namespace (api-block/resolve-class-prefix-for-db this))]
+                      :class-ident-namespace class-ident-namespace)]
      (p/let [tag (db-page-handler/<create-class! title opts')]
      (p/let [tag (db-page-handler/<create-class! title opts')]
        (sdk-utils/result->js tag)))))
        (sdk-utils/result->js tag)))))
 
 
@@ -254,21 +259,28 @@
                                                 (:db/id extend))))
                                                 (:db/id extend))))
 
 
 (defn get-tag [class-uuid-or-ident-or-title]
 (defn get-tag [class-uuid-or-ident-or-title]
-  (this-as
-   this
-   (let [title-or-ident (-> (if-not (string? class-uuid-or-ident-or-title)
-                              (str class-uuid-or-ident-or-title)
-                              class-uuid-or-ident-or-title)
-                            (string/replace #"^:+" ""))
-         eid (if (text/namespace-page? title-or-ident)
-               (keyword title-or-ident)
-               (if (util/uuid-string? title-or-ident)
-                 (when-let [id (sdk-utils/uuid-or-throw-error title-or-ident)]
-                   [:block/uuid id])
-                 (keyword (api-block/resolve-class-prefix-for-db this) title-or-ident)))
-         tag (db/entity eid)]
-     (when (ldb/class? tag)
-       (sdk-utils/result->js tag)))))
+  (this-as this
+           (let [eid (if (number? class-uuid-or-ident-or-title)
+                       class-uuid-or-ident-or-title
+                       (let [title-or-ident (-> (if-not (string? class-uuid-or-ident-or-title)
+                                                  (str class-uuid-or-ident-or-title)
+                                                  class-uuid-or-ident-or-title)
+                                                (string/replace #"^:+" ""))]
+                         (if (text/namespace-page? title-or-ident)
+                           (keyword title-or-ident)
+                           (if (util/uuid-string? title-or-ident)
+                             (when-let [id (sdk-utils/uuid-or-throw-error title-or-ident)]
+                               [:block/uuid id])
+                             (keyword (api-block/resolve-class-prefix-for-db this) title-or-ident)))))
+                 tag (db/entity eid)]
+             (when (ldb/class? tag)
+               (sdk-utils/result->js tag)))))
+
+(defn get-tags-by-name [name]
+  (when-let [tags (some->> (entity-util/get-pages-by-name (db-conn/get-db) name)
+                           (map #(some-> % (first) (db/entity)))
+                           (filter ldb/class?))]
+    (sdk-utils/result->js tags)))
 
 
 (defn tag-add-property [tag-id property-id-or-name]
 (defn tag-add-property [tag-id property-id-or-name]
   (p/let [tag (db/get-case-page tag-id)
   (p/let [tag (db/get-case-page tag-id)

+ 57 - 63
src/main/logseq/api/editor.cljs

@@ -2,13 +2,14 @@
   "Editor related APIs"
   "Editor related APIs"
   (:require [cljs-bean.core :as bean]
   (:require [cljs-bean.core :as bean]
             [cljs.reader]
             [cljs.reader]
-            [clojure.string :as string]
             [frontend.commands :as commands]
             [frontend.commands :as commands]
             [frontend.date :as date]
             [frontend.date :as date]
             [frontend.db :as db]
             [frontend.db :as db]
             [frontend.db.async :as db-async]
             [frontend.db.async :as db-async]
             [frontend.db.model :as db-model]
             [frontend.db.model :as db-model]
             [frontend.db.utils :as db-utils]
             [frontend.db.utils :as db-utils]
+            [frontend.extensions.pdf.assets :as pdf-assets]
+            [frontend.handler.assets :as assets-handler]
             [frontend.handler.code :as code-handler]
             [frontend.handler.code :as code-handler]
             [frontend.handler.dnd :as editor-dnd-handler]
             [frontend.handler.dnd :as editor-dnd-handler]
             [frontend.handler.editor :as editor-handler]
             [frontend.handler.editor :as editor-handler]
@@ -24,6 +25,7 @@
             [goog.dom :as gdom]
             [goog.dom :as gdom]
             [logseq.api.block :as api-block]
             [logseq.api.block :as api-block]
             [logseq.api.db-based :as db-based-api]
             [logseq.api.db-based :as db-based-api]
+            [logseq.common.path :as path]
             [logseq.common.util.date-time :as date-time-util]
             [logseq.common.util.date-time :as date-time-util]
             [logseq.db :as ldb]
             [logseq.db :as ldb]
             [logseq.sdk.core]
             [logseq.sdk.core]
@@ -185,26 +187,13 @@
     block))
     block))
 
 
 (defn insert_block
 (defn insert_block
-  [block-uuid-or-page-name content ^js opts]
+  [id content ^js opts]
   (this-as this
   (this-as this
-           (when (string/blank? block-uuid-or-page-name)
-             (throw (js/Error. "Page title or block UUID shouldn't be empty.")))
-
-           (p/let [block? (util/uuid-string? (str block-uuid-or-page-name))
-                   block (<get-block (str block-uuid-or-page-name))]
-             (if (and block? (not block))
-               (throw (js/Error. "Block not exists"))
-               (p/let [{:keys [before start end sibling focus customUUID properties autoOrderedList schema]} (bean/->clj opts)
-                       [page-name block-uuid] (if (util/uuid-string? block-uuid-or-page-name)
-                                                [nil (uuid block-uuid-or-page-name)]
-                                                [block-uuid-or-page-name nil])
-                       page-name (when page-name (util/page-name-sanity-lc page-name))
-                       _ (when (and page-name
-                                    (nil? (ldb/get-page (db/get-db) page-name)))
-                           (page-handler/<create! block-uuid-or-page-name {}))
+           (p/let [block (<get-block id)]
+             (when-let [block-uuid (:block/uuid block)]
+               (p/let [{:keys [before start end sibling customUUID properties autoOrderedList schema]} (bean/->clj opts)
                        custom-uuid (or customUUID (:id properties))
                        custom-uuid (or customUUID (:id properties))
                        custom-uuid (when custom-uuid (sdk-utils/uuid-or-throw-error custom-uuid))
                        custom-uuid (when custom-uuid (sdk-utils/uuid-or-throw-error custom-uuid))
-                       edit-block? (if (nil? focus) true focus)
                        _ (when (and custom-uuid (db-model/query-block-by-uuid custom-uuid))
                        _ (when (and custom-uuid (db-model/query-block-by-uuid custom-uuid))
                            (throw (js/Error.
                            (throw (js/Error.
                                    (util/format "Custom block UUID already exists (%s)." custom-uuid))))
                                    (util/format "Custom block UUID already exists (%s)." custom-uuid))))
@@ -227,8 +216,7 @@
                               :before? before?
                               :before? before?
                               :start? start
                               :start? start
                               :end? end
                               :end? end
-                              :edit-block? edit-block?
-                              :page page-name
+                              :edit-block? false
                               :custom-uuid custom-uuid
                               :custom-uuid custom-uuid
                               :ordered-list? (if (boolean? autoOrderedList) autoOrderedList false)}]
                               :ordered-list? (if (boolean? autoOrderedList) autoOrderedList false)}]
                  (db-based-api/insert-block this content properties schema opts'))))))
                  (db-based-api/insert-block this content properties schema opts'))))))
@@ -245,17 +233,18 @@
              (db-based-api/insert-batch-blocks this block blocks' opts))))))))
              (db-based-api/insert-batch-blocks this block blocks' opts))))))))
 
 
 (def remove_block
 (def remove_block
-  (fn [block-uuid ^js _opts]
-    (p/let [repo            (state/get-current-repo)
-            _ (<get-block block-uuid {:children? false})]
-      (editor-handler/delete-block-aux!
-       {:block/uuid (sdk-utils/uuid-or-throw-error block-uuid) :repo repo}))))
+  (fn [id ^js _opts]
+    (p/let [repo (state/get-current-repo)
+            block (<get-block id {:children? false})]
+      (when-let [block-uuid (:block/uuid block)]
+        (editor-handler/delete-block-aux!
+         {:block/uuid block-uuid :repo repo})))))
 
 
 (def update_block
 (def update_block
-  (fn [block-uuid content ^js opts]
+  (fn [id content ^js opts]
     (this-as
     (this-as
      this
      this
-     (p/let [block (<get-block block-uuid {:children? false})
+     (p/let [block (<get-block id {:children? false})
              opts' (bean/->clj opts)]
              opts' (bean/->clj opts)]
        (when block
        (when block
          (db-based-api/update-block this block content opts'))))))
          (db-based-api/update-block this block content opts'))))))
@@ -295,9 +284,8 @@
       (get_block (:block/uuid block) opts))))
       (get_block (:block/uuid block) opts))))
 
 
 (def get_previous_sibling_block
 (def get_previous_sibling_block
-  (fn [block-uuid ^js opts]
-    (p/let [id (sdk-utils/uuid-or-throw-error block-uuid)
-            block (<get-block id)
+  (fn [id ^js opts]
+    (p/let [block (<get-block id)
             ;; Load all children blocks
             ;; Load all children blocks
             _ (api-block/<sync-children-blocks! block)]
             _ (api-block/<sync-children-blocks! block)]
       (when block
       (when block
@@ -305,9 +293,8 @@
           (get_block (:block/uuid sibling) opts))))))
           (get_block (:block/uuid sibling) opts))))))
 
 
 (def get_next_sibling_block
 (def get_next_sibling_block
-  (fn [block-uuid ^js opts]
-    (p/let [id (sdk-utils/uuid-or-throw-error block-uuid)
-            block (<get-block id)
+  (fn [id ^js opts]
+    (p/let [block (<get-block id)
             ;; Load all children blocks
             ;; Load all children blocks
             _ (api-block/<sync-children-blocks! block)]
             _ (api-block/<sync-children-blocks! block)]
       (when block
       (when block
@@ -315,11 +302,11 @@
           (get_block (:block/uuid sibling) opts))))))
           (get_block (:block/uuid sibling) opts))))))
 
 
 (def set_block_collapsed
 (def set_block_collapsed
-  (fn [block-uuid ^js opts]
-    (p/let [block-uuid (sdk-utils/uuid-or-throw-error block-uuid)
-            block (<get-block block-uuid {:children? false})]
+  (fn [id ^js opts]
+    (p/let [block (<get-block id {:children? false})]
       (when block
       (when block
-        (let [opts (bean/->clj opts)
+        (let [block-uuid (:block/uuid block)
+              opts (bean/->clj opts)
               opts (if (or (string? opts) (boolean? opts)) {:flag opts} opts)
               opts (if (or (string? opts) (boolean? opts)) {:flag opts} opts)
               {:keys [flag]} opts
               {:keys [flag]} opts
               flag (if (= "toggle" flag)
               flag (if (= "toggle" flag)
@@ -422,35 +409,29 @@
 
 
 ;; block properties
 ;; block properties
 (defn upsert_block_property
 (defn upsert_block_property
-  [block-uuid key ^js value ^js options]
-  (this-as
-   this
-   (p/let [key' (api-block/sanitize-user-property-name key)
-           opts (bean/->clj options)
-           block-uuid (sdk-utils/uuid-or-throw-error block-uuid)
-           block (<get-block block-uuid {:children? false})
-           value (bean/->clj value)]
-     (when block
-       (db-based-api/upsert-block-property this block key' value opts)))))
+  [id key ^js value ^js options]
+  (this-as this
+           (p/let [key' (api-block/sanitize-user-property-name key)
+                   opts (bean/->clj options)
+                   block (<get-block id {:children? false})
+                   value (bean/->clj value)]
+             (when block
+               (db-based-api/upsert-block-property this block key' value opts)))))
 
 
 (defn remove_block_property
 (defn remove_block_property
-  [block-uuid key]
+  [id key]
   (this-as this
   (this-as this
-           (p/let [key (api-block/sanitize-user-property-name key)
-                   block-uuid (sdk-utils/uuid-or-throw-error block-uuid)
-                   _block (<get-block block-uuid {:children? false})
-                   key-ns? (namespace (keyword key))
-                   key (if (not key-ns?)
-                         (api-block/get-db-ident-from-property-name key this)
-                         key)]
-             (property-handler/remove-block-property! block-uuid key))))
+           (p/let [block (<get-block id {:children? false})]
+             (when-let [block-uuid (:block/uuid block)]
+               (let [key (api-block/sanitize-user-property-name key)
+                     key (api-block/get-db-ident-from-property-name key this)]
+                 (property-handler/remove-block-property! block-uuid key))))))
 
 
 (defn get_block_property
 (defn get_block_property
-  [block-uuid key]
+  [id key]
   (this-as this
   (this-as this
-           (p/let [block-uuid (sdk-utils/uuid-or-throw-error block-uuid)
-                   _block (<get-block block-uuid {:children? false})]
-             (when-let [properties (some-> block-uuid (db-model/get-block-by-uuid) (:block/properties))]
+           (p/let [block (<get-block id {:children? false})]
+             (when-let [properties (some-> block (:block/uuid) (db-model/get-block-by-uuid) (:block/properties))]
                (when (seq properties)
                (when (seq properties)
                  (let [property-name (api-block/sanitize-user-property-name key)
                  (let [property-name (api-block/sanitize-user-property-name key)
                        ident (api-block/get-db-ident-from-property-name property-name this)
                        ident (api-block/get-db-ident-from-property-name property-name this)
@@ -470,9 +451,8 @@
                        (bean/->js (sdk-utils/normalize-keyword-for-json property-value)))))))))
                        (bean/->js (sdk-utils/normalize-keyword-for-json property-value)))))))))
 
 
 (def get_block_properties
 (def get_block_properties
-  (fn [block-uuid]
-    (p/let [block-uuid (sdk-utils/uuid-or-throw-error block-uuid)
-            block (<get-block block-uuid {:children? false})]
+  (fn [id]
+    (p/let [block (<get-block id {:children? false})]
       (when block
       (when block
         (let [properties (api-block/into-readable-db-properties (:block/properties block))]
         (let [properties (api-block/into-readable-db-properties (:block/properties block))]
           (sdk-utils/result->js properties))))))
           (sdk-utils/result->js properties))))))
@@ -482,3 +462,17 @@
   (p/let [page (<get-block id-or-page-name {:children? false})]
   (p/let [page (<get-block id-or-page-name {:children? false})]
     (when-let [id (:block/uuid page)]
     (when-let [id (:block/uuid page)]
       (get_block_properties id))))
       (get_block_properties id))))
+
+(defn open_pdf_viewer
+  [block-identity-or-file-url]
+  (p/let [[block href] (if (and (string? block-identity-or-file-url)
+                                (or (path/protocol-url? block-identity-or-file-url)
+                                    (path/absolute? block-identity-or-file-url)))
+                         [nil block-identity-or-file-url]
+                         (p/let [block (<get-block block-identity-or-file-url {:children? false})]
+                           [block (if block
+                                    (util/format "../assets/%s.pdf" (:block/uuid block))
+                                    block-identity-or-file-url)]))
+          href' (assets-handler/<make-asset-url href)]
+    (when-let [current (pdf-assets/inflate-asset href {:block block :href href'})]
+      (state/set-current-pdf! current))))