diff --git a/src/main/frontend/handler/common/page.cljs b/src/main/frontend/handler/common/page.cljs index b44e5b41a1..f8c124d0c6 100644 --- a/src/main/frontend/handler/common/page.cljs +++ b/src/main/frontend/handler/common/page.cljs @@ -8,6 +8,7 @@ [frontend.handler.route :as route-handler] [frontend.state :as state] [frontend.worker.handler.page :as worker-page] + [frontend.worker.handler.page.db-based.page :as db-worker-page] [logseq.common.util :as common-util] [logseq.common.config :as common-config] [frontend.handler.ui :as ui-handler] @@ -67,8 +68,8 @@ (block-handler/edit-block! first-block :max {:container-id :unknown-container}) page) ;; create first block and then focus it - (p/let [blocks-tx (worker-page/build-first-block-tx (:block/uuid page) - (or (:format options) (common-config/get-preferred-format config))) + (p/let [blocks-tx (db-worker-page/build-first-block-tx (:block/uuid page) + (or (:format options) (common-config/get-preferred-format config))) _ (ldb/transact! conn blocks-tx {:outliner-op :insert-blocks}) first-block (ldb/get-first-child @conn (:db/id page))] (block-handler/edit-block! first-block :max {:container-id :unknown-container}) diff --git a/src/main/frontend/worker/handler/page.cljs b/src/main/frontend/worker/handler/page.cljs index 55e621b1b3..a8ddcc630f 100644 --- a/src/main/frontend/worker/handler/page.cljs +++ b/src/main/frontend/worker/handler/page.cljs @@ -3,185 +3,18 @@ (:require [logseq.db :as ldb] [logseq.graph-parser.db :as gp-db] [logseq.graph-parser.block :as gp-block] - [logseq.graph-parser.property :as gp-property] [logseq.db.sqlite.util :as sqlite-util] [datascript.core :as d] - [clojure.string :as string] - [logseq.graph-parser.text :as text] - [logseq.common.util :as common-util] [logseq.common.config :as common-config] [logseq.db.frontend.content :as db-content] - [frontend.worker.date :as date] - [logseq.db.frontend.order :as db-order] - [logseq.db.frontend.property.util :as db-property-util] - [logseq.db.frontend.property.build :as db-property-build] - [logseq.db.frontend.class :as db-class])) - -(defn file-based-properties-block - [repo conn config date-formatter properties format page] - (let [content (gp-property/insert-properties repo format "" properties) - refs (gp-block/get-page-refs-from-properties properties @conn date-formatter config)] - {:block/pre-block? true - :block/uuid (ldb/new-block-id) - :block/properties properties - :block/properties-order (keys properties) - :block/refs refs - :block/order (db-order/gen-key nil nil) - :block/format format - :block/content content - :block/parent page - :block/page page})) - -(defn- build-page-tx [repo conn config date-formatter format properties page {:keys [whiteboard? class? tags]}] - (when (:block/uuid page) - (let [page-entity [:block/uuid (:block/uuid page)] - page' (merge page - (when whiteboard? {:block/type "whiteboard"}) - (when tags {:block/tags (mapv #(hash-map :db/id - (:db/id (d/entity @conn [:block/uuid %]))) - tags)}))] - (if (sqlite-util/db-based-graph? repo) - (let [property-vals-tx-m - ;; Builds property values for built-in properties like logseq.property.pdf/file - (db-property-build/build-property-values-tx-m - page' - (->> properties - (keep (fn [[k v]] - (when (db-property-util/built-in-has-ref-value? k) - [k v]))) - (into {})))] - (cond-> [(if class? (db-class/build-new-class @conn page') page')] - (seq property-vals-tx-m) - (into (vals property-vals-tx-m)) - true - (conj (merge {:block/uuid (:block/uuid page)} - properties - (db-property-build/build-properties-with-ref-values property-vals-tx-m))))) - (let [file-page (merge page' - (when (seq properties) {:block/properties properties}))] - (if (and (seq properties) - (not whiteboard?) - (ldb/page-empty? @conn (:block/name page))) - [file-page (file-based-properties-block repo conn config date-formatter properties format page-entity)] - [file-page])))))) - -(defn get-title-and-pagename - [title] - (let [title (-> (string/trim title) - (text/page-ref-un-brackets!) - ;; remove `#` from tags - (string/replace #"^#+" "")) - title (common-util/remove-boundary-slashes title) - page-name (common-util/page-name-sanity-lc title)] - [title page-name])) - -(defn build-first-block-tx - [page-uuid format] - (let [page-id [:block/uuid page-uuid]] - [(sqlite-util/block-with-timestamps - {:block/uuid (ldb/new-block-id) - :block/page page-id - :block/parent page-id - :block/order (db-order/gen-key nil nil) - :block/content "" - :block/format format})])) - -(defn- file-based-create! - [repo conn config title {:keys [create-first-block? format properties uuid persist-op? whiteboard? class? today-journal?] - :or {create-first-block? true - format nil - properties nil - uuid nil - persist-op? true} - :as options}] - (let [date-formatter (common-config/get-date-formatter config) - split-namespace? (not (or (string/starts-with? title "hls__") - (date/valid-journal-title? date-formatter title))) - [title page-name] (get-title-and-pagename title) - with-uuid? (if (uuid? uuid) uuid true)] - (when-not (ldb/get-page @conn page-name) - (let [pages (if split-namespace? - (common-util/split-namespace-pages title) - [title]) - format (or format (common-config/get-preferred-format config)) - pages (map (fn [page] - ;; only apply uuid to the deepest hierarchy of page to create if provided. - (-> (gp-block/page-name->map page (if (= page title) with-uuid? true) @conn true date-formatter :class? class?) - (assoc :block/format format))) - pages) - txs (->> pages - ;; for namespace pages, only last page need properties - drop-last - (mapcat #(build-page-tx repo conn config date-formatter format nil % {})) - (remove nil?)) - txs (map-indexed (fn [i page] - (if (zero? i) - page - (assoc page :block/namespace - [:block/uuid (:block/uuid (nth txs (dec i)))]))) - txs) - page-uuid (:block/uuid (last pages)) - page-txs (build-page-tx repo conn config date-formatter format properties (last pages) (select-keys options [:whiteboard? :class? :tags])) - page-txs (if (seq txs) - (update page-txs 0 - (fn [p] - (assoc p :block/namespace [:block/uuid (:block/uuid (last txs))]))) - page-txs) - first-block-tx (when (and - create-first-block? - (not (or whiteboard? class?)) - page-txs) - (build-first-block-tx (:block/uuid (first page-txs)) format)) - txs (concat - txs - page-txs - first-block-tx) - [page-uuid result] (when (seq txs) - [page-uuid (ldb/transact! conn txs (cond-> {:persist-op? persist-op? - :outliner-op :create-page} - today-journal? - (assoc :create-today-journal? true - :today-journal-name page-name)))])] - [result page-name page-uuid])))) - -(defn db-based-create! - [repo conn config title - {:keys [create-first-block? properties uuid persist-op? whiteboard? class? today-journal?] - :or {create-first-block? true - properties nil - uuid nil - persist-op? true} - :as options}] - (let [date-formatter (common-config/get-date-formatter config) - [title page-name] (get-title-and-pagename title) - with-uuid? (if (uuid? uuid) uuid true)] - (when-not (ldb/get-page @conn page-name) - (let [format :markdown - page (-> (gp-block/page-name->map title with-uuid? @conn true date-formatter :class? class?) - (assoc :block/format format)) - page-uuid (:block/uuid page) - page-txs (build-page-tx repo conn config date-formatter format properties page (select-keys options [:whiteboard? :class? :tags])) - first-block-tx (when (and - create-first-block? - (not (or whiteboard? class?)) - page-txs) - (build-first-block-tx (:block/uuid (first page-txs)) format)) - txs (concat - page-txs - first-block-tx) - [page-uuid result] (when (seq txs) - [page-uuid (ldb/transact! conn txs (cond-> {:persist-op? persist-op? - :outliner-op :create-page} - today-journal? - (assoc :create-today-journal? true - :today-journal-name page-name)))])] - [result page-name page-uuid])))) + [frontend.worker.handler.page.db-based.page :as db-worker-page] + [frontend.worker.handler.page.file-based.page :as file-worker-page])) (defn rtc-create-page! [conn config title {:keys [uuid]}] (assert (uuid? uuid) (str "rtc-create-page! `uuid` is not a uuid " uuid)) (let [date-formatter (common-config/get-date-formatter config) - [title page-name] (get-title-and-pagename title) + [title page-name] (db-worker-page/get-title-and-pagename title) page (-> (gp-block/page-name->map title uuid @conn true date-formatter {:skip-existing-page-check? true}) (assoc :block/format :markdown)) @@ -202,8 +35,8 @@ TODO: Add other options" [repo conn config title & options] (if (ldb/db-based-graph? @conn) - (db-based-create! repo conn config title options) - (file-based-create! repo conn config title options))) + (db-worker-page/create! conn config title options) + (file-worker-page/create! repo conn config title options))) (defn db-refs->page "Replace [[page name]] with page name" diff --git a/src/main/frontend/worker/handler/page/db_based/page.cljs b/src/main/frontend/worker/handler/page/db_based/page.cljs new file mode 100644 index 0000000000..2d772f6eb2 --- /dev/null +++ b/src/main/frontend/worker/handler/page/db_based/page.cljs @@ -0,0 +1,93 @@ +(ns frontend.worker.handler.page.db-based.page + "Page operations for DB graphs" + (:require [logseq.db :as ldb] + [logseq.graph-parser.block :as gp-block] + [logseq.db.sqlite.util :as sqlite-util] + [datascript.core :as d] + [clojure.string :as string] + [logseq.graph-parser.text :as text] + [logseq.common.util :as common-util] + [logseq.common.config :as common-config] + [logseq.db.frontend.order :as db-order] + [logseq.db.frontend.property.util :as db-property-util] + [logseq.db.frontend.property.build :as db-property-build] + [logseq.db.frontend.class :as db-class])) + +(defn- build-page-tx [conn properties page {:keys [whiteboard? class? tags]}] + (when (:block/uuid page) + (let [page' (merge page + (when whiteboard? {:block/type "whiteboard"}) + (when tags {:block/tags (mapv #(hash-map :db/id + (:db/id (d/entity @conn [:block/uuid %]))) + tags)})) + property-vals-tx-m + ;; Builds property values for built-in properties like logseq.property.pdf/file + (db-property-build/build-property-values-tx-m + page' + (->> properties + (keep (fn [[k v]] + (when (db-property-util/built-in-has-ref-value? k) + [k v]))) + (into {})))] + (cond-> [(if class? (db-class/build-new-class @conn page') page')] + (seq property-vals-tx-m) + (into (vals property-vals-tx-m)) + true + (conj (merge {:block/uuid (:block/uuid page)} + properties + (db-property-build/build-properties-with-ref-values property-vals-tx-m))))))) + +;; TODO: Revisit title cleanup as this was copied from file implementation +(defn get-title-and-pagename + [title] + (let [title (-> (string/trim title) + (text/page-ref-un-brackets!) + ;; remove `#` from tags + (string/replace #"^#+" "")) + title (common-util/remove-boundary-slashes title) + page-name (common-util/page-name-sanity-lc title)] + [title page-name])) + +(defn build-first-block-tx + [page-uuid format] + (let [page-id [:block/uuid page-uuid]] + [(sqlite-util/block-with-timestamps + {:block/uuid (ldb/new-block-id) + :block/page page-id + :block/parent page-id + :block/order (db-order/gen-key nil nil) + :block/content "" + :block/format format})])) + +(defn create! + [conn config title + {:keys [create-first-block? properties uuid persist-op? whiteboard? class? today-journal?] + :or {create-first-block? true + properties nil + uuid nil + persist-op? true} + :as options}] + (let [date-formatter (common-config/get-date-formatter config) + [title page-name] (get-title-and-pagename title) + with-uuid? (if (uuid? uuid) uuid true)] + (when-not (ldb/get-case-page @conn page-name) + (let [format :markdown + page (-> (gp-block/page-name->map title with-uuid? @conn true date-formatter :class? class?) + (assoc :block/format format)) + page-uuid (:block/uuid page) + page-txs (build-page-tx conn properties page (select-keys options [:whiteboard? :class? :tags])) + first-block-tx (when (and + create-first-block? + (not (or whiteboard? class?)) + page-txs) + (build-first-block-tx (:block/uuid (first page-txs)) format)) + txs (concat + page-txs + first-block-tx) + [page-uuid result] (when (seq txs) + [page-uuid (ldb/transact! conn txs (cond-> {:persist-op? persist-op? + :outliner-op :create-page} + today-journal? + (assoc :create-today-journal? true + :today-journal-name page-name)))])] + [result page-name page-uuid])))) \ No newline at end of file diff --git a/src/main/frontend/worker/handler/page/file_based/page.cljs b/src/main/frontend/worker/handler/page/file_based/page.cljs new file mode 100644 index 0000000000..35c392778c --- /dev/null +++ b/src/main/frontend/worker/handler/page/file_based/page.cljs @@ -0,0 +1,123 @@ +(ns frontend.worker.handler.page.file-based.page + "Page operations for file graphs" + (:require [logseq.db :as ldb] + [logseq.graph-parser.block :as gp-block] + [logseq.graph-parser.property :as gp-property] + [logseq.outliner.core :as outliner-core] + [datascript.core :as d] + [clojure.string :as string] + [logseq.graph-parser.text :as text] + [logseq.common.util :as common-util] + [logseq.common.config :as common-config] + [frontend.worker.date :as date] + [logseq.db.frontend.order :as db-order])) + +(defn- file-based-properties-block + [repo conn config date-formatter properties format page] + (let [content (gp-property/insert-properties repo format "" properties) + refs (gp-block/get-page-refs-from-properties properties @conn date-formatter config)] + {:block/pre-block? true + :block/uuid (ldb/new-block-id) + :block/properties properties + :block/properties-order (keys properties) + :block/refs refs + :block/order (db-order/gen-key nil nil) + :block/format format + :block/content content + :block/parent page + :block/page page})) + +(defn- build-page-tx [repo conn config date-formatter format properties page {:keys [whiteboard? tags]}] + (when (:block/uuid page) + (let [page-entity [:block/uuid (:block/uuid page)] + page' (merge page + (when whiteboard? {:block/type "whiteboard"}) + (when tags {:block/tags (mapv #(hash-map :db/id + (:db/id (d/entity @conn [:block/uuid %]))) + tags)})) + file-page (merge page' + (when (seq properties) {:block/properties properties}))] + (if (and (seq properties) + (not whiteboard?) + (ldb/page-empty? @conn (:block/name page))) + [file-page (file-based-properties-block repo conn config date-formatter properties format page-entity)] + [file-page])))) + +(defn get-title-and-pagename + [title] + (let [title (-> (string/trim title) + (text/page-ref-un-brackets!) + ;; remove `#` from tags + (string/replace #"^#+" "")) + title (common-util/remove-boundary-slashes title) + page-name (common-util/page-name-sanity-lc title)] + [title page-name])) + +(defn- build-first-block-tx + [page-uuid format] + (let [page-id [:block/uuid page-uuid]] + [(outliner-core/block-with-timestamps + {:block/uuid (ldb/new-block-id) + :block/page page-id + :block/parent page-id + :block/order (db-order/gen-key nil nil) + :block/content "" + :block/format format})])) + +(defn create! + [repo conn config title {:keys [create-first-block? format properties uuid persist-op? whiteboard? today-journal?] + :or {create-first-block? true + format nil + properties nil + uuid nil + persist-op? true} + :as options}] + (let [date-formatter (common-config/get-date-formatter config) + split-namespace? (not (or (string/starts-with? title "hls__") + (date/valid-journal-title? date-formatter title))) + [title page-name] (get-title-and-pagename title) + with-uuid? (if (uuid? uuid) uuid true)] + (when-not (ldb/get-page @conn page-name) + (let [pages (if split-namespace? + (common-util/split-namespace-pages title) + [title]) + format (or format (common-config/get-preferred-format config)) + pages (map (fn [page] + ;; only apply uuid to the deepest hierarchy of page to create if provided. + (-> (gp-block/page-name->map page (if (= page title) with-uuid? true) @conn true date-formatter) + (assoc :block/format format))) + pages) + txs (->> pages + ;; for namespace pages, only last page need properties + drop-last + (mapcat #(build-page-tx repo conn config date-formatter format nil % {})) + (remove nil?)) + txs (map-indexed (fn [i page] + (if (zero? i) + page + (assoc page :block/namespace + [:block/uuid (:block/uuid (nth txs (dec i)))]))) + txs) + page-uuid (:block/uuid (last pages)) + page-txs (build-page-tx repo conn config date-formatter format properties (last pages) (select-keys options [:whiteboard? :tags])) + page-txs (if (seq txs) + (update page-txs 0 + (fn [p] + (assoc p :block/namespace [:block/uuid (:block/uuid (last txs))]))) + page-txs) + first-block-tx (when (and + create-first-block? + (not whiteboard?) + page-txs) + (build-first-block-tx (:block/uuid (first page-txs)) format)) + txs (concat + txs + page-txs + first-block-tx) + [page-uuid result] (when (seq txs) + [page-uuid (ldb/transact! conn txs (cond-> {:persist-op? persist-op? + :outliner-op :create-page} + today-journal? + (assoc :create-today-journal? true + :today-journal-name page-name)))])] + [result page-name page-uuid]))))