Merge branch 'feat/db' into chore/whiteboards-cleanup

pull/10906/head
Konstantinos Kaloutas 2024-01-23 11:57:57 +02:00
commit f984701c27
26 changed files with 291 additions and 246 deletions

View File

@ -38,7 +38,7 @@ jobs:
- name: Build Released-Web
run: |
yarn gulp:build && clojure -M:cljs release app --config-merge '{:compiler-options {:source-map-include-sources-content false :source-map-detail-level :symbols}}'
rsync -avz --exclude node_modules --exclude '*.js.map' --exclude android --exclude ios ./static/ ./public/static/
rsync -avz --exclude node_modules --exclude android --exclude ios ./static/ ./public/static/
ls -lR ./public
- name: Publish to Cloudflare Pages

View File

@ -18,7 +18,7 @@
[logseq.db.sqlite.util :as sqlite-util]
[cljs.pprint :as pprint]))
(def block-map
(def ^:private block-map
(mu/optional-keys
[:map
[:db/id :int]
@ -28,12 +28,12 @@
[:block/parent :map]
[:block/page :map]]))
(def block-map-or-entity
(def ^:private block-map-or-entity
[:or [:fn de/entity?] block-map])
(defrecord Block [data])
(defrecord ^:api Block [data])
(defn block
(defn ^:api block
[db m]
(assert (or (map? m) (de/entity? m)) (common-util/format "block data must be map or entity, got: %s %s" (type m) m))
(let [e (if (or (de/entity? m)
@ -48,11 +48,11 @@
:block/uuid (:block/uuid entity)))))]
(->Block e)))
(defn get-data
(defn ^:api get-data
[block]
(:data block))
(defn get-block-by-id
(defn- get-block-by-id
[db id]
(let [r (ldb/get-by-id db (outliner-u/->block-lookup-ref id))]
(when r (->Block r))))
@ -74,7 +74,7 @@
(assoc :block/created-at updated-at))]
block))
(defn block-with-updated-at
(defn ^:api block-with-updated-at
[block]
(let [updated-at (common-util/time-ms)]
(assoc block :block/updated-at updated-at)))
@ -192,7 +192,7 @@
merge-tx))))))
(reset! (:editor/create-page? @state/state) false))))
(defn rebuild-block-refs
(defn ^:api rebuild-block-refs
[repo conn date-formatter block new-properties & {:keys [skip-content-parsing?]}]
(let [db @conn
property-key-refs (keys new-properties)
@ -400,7 +400,7 @@
children (ldb/get-block-immediate-children @conn parent-id)]
(map #(block @conn %) children))))
(defn get-right-sibling
(defn ^:api get-right-sibling
[db db-id]
(when db-id
(ldb/get-right-sibling db db-id)))
@ -537,7 +537,7 @@
(mapcat #(tree-seq map? children-key %))
(map #(dissoc % :block/children)))))
(defn save-block
(defn ^:api save-block
"Save the `block`."
[repo conn date-formatter block']
{:pre [(map? block')]}
@ -577,7 +577,7 @@
;;; ### insert-blocks, delete-blocks, move-blocks
(defn fix-top-level-blocks
(defn ^:api fix-top-level-blocks
"Blocks with :block/level"
[blocks]
(let [top-level-blocks (filter #(= (:block/level %) 1) blocks)
@ -694,7 +694,7 @@
result)))
(defn blocks-with-level
(defn ^:api blocks-with-level
"Calculate `:block/level` for all the `blocks`. Blocks should be sorted already."
[blocks]
{:pre [(seq blocks)]}
@ -723,7 +723,7 @@
m' (vec (conj m block))]
(recur m' (rest blocks)))))))
(defn ^:large-vars/cleanup-todo insert-blocks
(defn- ^:large-vars/cleanup-todo insert-blocks
"Insert blocks as children (or siblings) of target-node.
Args:
`conn`: db connection.
@ -844,7 +844,7 @@
non-consecutive-blocks)))) page-blocks)
(remove nil?)))))
(defn delete-block
(defn ^:api delete-block
"Delete block from the tree."
[repo conn txs-state node {:keys [children? children-check? date-formatter]
:or {children-check? true}}]
@ -933,7 +933,7 @@
(:db/id target-block))
sibling?)))
(defn move-blocks
(defn- move-blocks
"Move `blocks` to `target-block` as siblings or children."
[repo conn blocks target-block {:keys [_sibling? _up? outliner-op _indent?]
:as opts}]
@ -979,7 +979,7 @@
{:tx-data full-tx
:tx-meta tx-meta}))))))))
(defn move-blocks-up-down
(defn- move-blocks-up-down
"Move blocks up/down."
[repo conn blocks up?]
{:pre [(seq blocks) (boolean? up?)]}
@ -1013,7 +1013,7 @@
(move-blocks repo conn blocks right (merge opts {:sibling? sibling?
:up? up?})))))))
(defn ^:large-vars/cleanup-todo indent-outdent-blocks
(defn- ^:large-vars/cleanup-todo indent-outdent-blocks
"Indent or outdent `blocks`."
[repo conn blocks indent? & {:keys [get-first-block-original logical-outdenting?]}]
{:pre [(seq blocks) (boolean? indent?)]}

View File

@ -27,7 +27,7 @@
v)))
x)))))
(defn update-refs-and-macros
(defn- update-refs-and-macros
"When a block is deleted, refs are updated and macros associated with the block are deleted"
[txs db repo opts set-state-fn]
(if (= :delete-blocks (:outliner-op opts))

View File

@ -4,12 +4,12 @@
#?(:cljs (:require-macros [logseq.outliner.transaction]))
#?(:cljs (:require [malli.core :as m])))
(def transact-opts [:or :symbol :map])
(def ^:private transact-opts [:or :symbol :map])
#?(:org.babashka/nbb nil
:cljs (m/=> transact! [:=> [:cat transact-opts :any] :any]))
(defmacro transact!
(defmacro ^:api transact!
"Batch all the transactions in `body` to a single transaction, Support nested transact! calls.
Currently there are no options, it'll execute body and collect all transaction data generated by body.
If no transactions are included in `body`, it does not save a transaction.

View File

@ -80,7 +80,7 @@
(assoc root' :block/children children)
root')))
(defn block-entity->map
(defn ^:api block-entity->map
[e]
(cond-> {:db/id (:db/id e)
:block/uuid (:block/uuid e)
@ -93,7 +93,7 @@
(:block/children e)
(assoc :block/children (:block/children e))))
(defn filter-top-level-blocks
(defn ^:api filter-top-level-blocks
[blocks]
(let [id->blocks (zipmap (map :db/id blocks) blocks)]
(filter #(nil?
@ -121,7 +121,7 @@
(if sorted-nested-children [parent sorted-nested-children] [parent])))
parents))
(defn sort-blocks
(defn ^:api sort-blocks
"sort blocks by parent & left"
[blocks-exclude-root root]
(let [parent-groups (atom (group-by :block/parent blocks-exclude-root))]

View File

@ -7,7 +7,7 @@
[datascript.impl.entity :as e]
[logseq.common.util :as common-util]))
(defn block-id?
(defn- block-id?
[id]
(or
(number? id)

View File

@ -20,7 +20,7 @@ can be passed:
* :db-graph? - Boolean which indicates if graph is db based
* :default-notification-fn - Configure how errors are reported when creating the export.
Default is to throw an exception when it occurs."
[db static-dir graph-dir output-dir {:keys [notification-fn]
[db static-dir graph-dir output-dir {:keys [notification-fn dev?]
:or {notification-fn default-notification-fn}
:as options}]
(let [options' (cond-> options
@ -30,4 +30,5 @@ can be passed:
(assoc-in [:app-state :ui/radix-color] (:ui/radix-color options)))
{:keys [html asset-filenames]} (publish-html/build-html db options')]
(publish-export/create-export html static-dir graph-dir output-dir {:asset-filenames asset-filenames
:notification-fn notification-fn})))
:notification-fn notification-fn
:dev? dev?})))

View File

@ -22,21 +22,30 @@
(defn- cleanup-js-dir
"Moves used js files to the correct dir and removes unused js files"
[output-static-dir]
[output-static-dir source-static-dir {:keys [dev?]}]
(let [publishing-dir (node-path/join output-static-dir "js" "publishing")]
(p/let [_ (p/all (map (fn [file]
(fs/rmSync (node-path/join output-static-dir "js" file) #js {:force true}))
js-files))
_ (when dev?
(fse/remove (node-path/join output-static-dir "js" "cljs-runtime")))
_ (p/all (map (fn [file]
(fs/renameSync
(node-path/join publishing-dir file)
(node-path/join output-static-dir "js" file)))
(if dev?
(fs/symlinkSync
(node-path/join source-static-dir "js" "publishing" file)
(node-path/join output-static-dir "js" file))
(fs/renameSync
(node-path/join publishing-dir file)
(node-path/join output-static-dir "js" file))))
js-files))
_ (when dev?
(fs/symlinkSync (node-path/join source-static-dir "js" "publishing" "cljs-runtime")
(node-path/join output-static-dir "js" "cljs-runtime")))
;; remove publishing-dir
_ (p/all (map (fn [file]
(fs/rmSync (node-path/join publishing-dir file)))
(fs/readdirSync publishing-dir)))
_ (fs/rmdirSync publishing-dir)
_ (when-not dev? (p/all (map (fn [file]
(fs/rmSync (node-path/join publishing-dir file)))
(fs/readdirSync publishing-dir))))
_ (when-not dev? (fs/rmdirSync publishing-dir))
;; remove source map files
_ (p/all (map (fn [file]
(fs/rmSync (node-path/join output-static-dir "js" (str file ".map")) #js {:force true}))
@ -90,7 +99,7 @@
_ (fs/writeFileSync (node-path/join output-static-dir "css" "custom.css") custom-css)
custom-js (if (fs/existsSync custom-js-path) (str (fs/readFileSync custom-js-path)) "")
_ (fs/writeFileSync (node-path/join output-static-dir "js" "custom.js") custom-js)
_ (cleanup-js-dir output-static-dir)]
_ (cleanup-js-dir output-static-dir static-dir options)]
(notification-fn {:type "success"
:payload (str "Export public pages and publish assets to " output-dir " successfully 🎉")}))
(p/catch (fn [error]

View File

@ -122,6 +122,9 @@ necessary db filtering"
}
}(window.location))"]
;; TODO: should make this configurable
[:script {:src "static/js/react.production.min.js"}]
[:script {:src "static/js/react-dom.production.min.js"}]
[:script {:src "static/js/ui.js"}]
[:script {:src "static/js/shared.js"}]
[:script {:src "static/js/main.js"}]
[:script {:src "static/js/interact.min.js"}]

View File

@ -320,10 +320,14 @@ point out:
```sh
# One time setup
$ cd scripts && yarn install && cd -
# Build the export
# Build a release export
$ bb dev:publishing /path/to/graph-dir tmp/publish
# OR build a dev export with `clojure -M:cljs watch publishing` and then
$ bb dev:publishing /path/to/graph-dir tmp/publish --dev
# View the app in a browser
$ open tmp/publish/index.html
$ python3 -m http.server 8080 -d tmp/db-publish &; open http://localhost:8080
```
There are also some tasks under `nbb:` which are useful for inspecting database

View File

@ -21,7 +21,7 @@
output-path
{:repo-config repo-config :ui/theme "dark" :ui/radix-color :purple})))
(defn- publish-db-graph [static-dir graph-dir output-path]
(defn- publish-db-graph [static-dir graph-dir output-path opts]
(let [db-name (node-path/basename graph-dir)
conn (sqlite-db/open-db! (node-path/dirname graph-dir) db-name)
repo-config (-> (d/q '[:find ?content
@ -33,16 +33,16 @@
static-dir
graph-dir
output-path
{:repo-config repo-config :db-graph? true :ui/theme "dark" :ui/radix-color :cyan})))
(merge opts {:repo-config repo-config :db-graph? true :ui/theme "dark" :ui/radix-color :cyan}))))
(defn -main
[& args]
(when-not (= 3 (count args))
(when (< (count args) 3)
(println "Usage: $0 STATIC-DIR GRAPH-DIR OUT-DIR")
(js/process.exit 1))
(let [[static-dir graph-dir output-path]
;; Offset relative paths since they are run in a different directory than user is in
(map #(if (node-path/isAbsolute %) % (node-path/resolve ".." %)) args)]
(if (sqlite-cli/db-graph-directory? graph-dir)
(publish-db-graph static-dir graph-dir output-path)
(publish-db-graph static-dir graph-dir output-path {:dev? (contains? (set args) "--dev")})
(publish-file-graph static-dir graph-dir output-path))))

View File

@ -43,7 +43,8 @@
:externs ["datascript/externs.js"
"externs.js"]
:warnings {:fn-deprecated false
:redef false}}
:redef false}
:cross-chunk-method-motion false}
:build-hooks [(shadow.hooks/git-revision-hook "--long --always --dirty")]
:closure-defines {goog.debug.LOGGING_ENABLED true
frontend.modules.instrumentation.sentry/SENTRY-DSN #shadow/env "LOGSEQ_SENTRY_DSN"

View File

@ -61,12 +61,13 @@
(rum/defcs configure < rum/reactive
"Configure a class page"
[state page]
[state page {:keys [show-title?]
:or {show-title? true}}]
(let [page-id (:db/id page)
page (when page-id (db/sub-block page-id))]
(when page
[:div.property-configure.grid.gap-2
[:h1.title.mb-4 "Configure class"]
(when show-title? [:h1.title.mb-4 "Configure class"])
[:div.grid.grid-cols-5.gap-1.items-center.class-parent
[:div.col-span-2 "Parent class:"]

View File

@ -12,38 +12,41 @@
[frontend.handler.property.util :as pu]
[frontend.handler.db-based.property.util :as db-pu]
[frontend.ui :as ui]
[frontend.util :as util]
[frontend.state :as state]
[rum.core :as rum]))
[rum.core :as rum]
[logseq.shui.ui :as shui-ui]
[frontend.util :as util]
[clojure.set :as set]
[clojure.string :as string]))
(rum/defc page-properties < rum/reactive
[page {:keys [configure? show-page-properties?]}]
[page {:keys [configure? mode]}]
(let [types (:block/type page)
class? (contains? types "class")
property? (contains? types "property")
edit-input-id-prefix (str "edit-block-" (:block/uuid page))
configure-opts {:selected? false
:page-configure? true}
has-viewable-properties? (db-property-handler/block-has-viewable-properties? page)
has-class-properties? (seq (:properties (:block/schema page)))]
(when (or configure? has-viewable-properties? has-class-properties?)
[:div.ls-page-properties.mb-4 {:style {:padding 2}}
(when (or configure? has-viewable-properties? has-class-properties? property?)
[:div.ls-page-properties.mb-4
(if configure?
(cond
(and class? (not show-page-properties?) (not has-class-properties?))
[:div
[:div.mb-1 "Class properties:"]
(component-block/db-properties-cp {:editor-box editor/box}
page
(str edit-input-id-prefix "-schema")
(assoc configure-opts :class-schema? true))]
(and class? has-class-properties? (= :class mode))
nil
(and class? (not has-class-properties?))
(component-block/db-properties-cp {:editor-box editor/box}
page
(str edit-input-id-prefix "-schema")
(assoc configure-opts :class-schema? true))
(not (db-property-handler/block-has-viewable-properties? page))
[:div
[:div.mb-1 "Page properties:"]
(component-block/db-properties-cp {:editor-box editor/box}
page
(str edit-input-id-prefix "-page")
(assoc configure-opts :class-schema? false))])
(component-block/db-properties-cp {:editor-box editor/box}
page
(str edit-input-id-prefix "-page")
(assoc configure-opts :class-schema? false)))
(if config/publishing?
[:div.flex.flex-col.gap-4
(when has-viewable-properties?
@ -88,7 +91,7 @@
(rum/defc icon-row < rum/reactive
[page]
[:div.grid.grid-cols-5.gap-1.items-center.leading-8
[:div.grid.grid-cols-5.gap-1.items-center
[:label.col-span-2 "Icon:"]
(let [icon-value (pu/get-block-property-value page :icon)]
[:div.col-span-3.flex.flex-row.items-center.gap-2
@ -109,85 +112,43 @@
:title "Delete this icon"}
(ui/icon "X")])])])
(rum/defcs page-configure-inner <
(rum/local false ::show-page-properties?)
{:will-unmount (fn [state]
(let [on-unmount (nth (:rum/args state) 1)]
(on-unmount)))}
[state page _on-unmount opts]
(let [*show-page-properties? (::show-page-properties? state)
(rum/defc tags
[page]
(let [tags-property (pu/get-property :tags)]
(pv/property-value page tags-property
(map :block/uuid (:block/tags page))
{:page-cp (fn [config page]
(component-block/page-cp (assoc config :tag? true) page))})))
(rum/defc tags-row < rum/reactive
[page]
[:div.grid.grid-cols-5.gap-1.items-center
[:label.col-span-2 "Tags:"]
[:div.col-span-3.flex.flex-row.items-center.gap-2
(tags page)]])
(rum/defcs page-configure < rum/reactive
[state page *mode]
(let [*mode *mode
mode (rum/react *mode)
types (:block/type page)
class? (contains? types "class")
property? (contains? types "property")
class-or-property? (or class? property?)
page-opts {:configure? true
:show-page-properties? @*show-page-properties?}]
[:div.flex.flex-col.justify-between.p-4 {:style {:min-width 700
:min-height 400}}
[:div.flex.flex-col.gap-2
(cond
(not class-or-property?)
(when (and (not class?)
(not property?))
[:<>
(icon-row page)
(page-properties page page-opts)])
@*show-page-properties?
(page-properties page page-opts)
:else
[:<>
(when class?
(class-component/configure page))
(when class?
(icon-row page))
(when class?
(page-properties page page-opts))
(when (and property? (not class?))
[:h2.title "Configure property"])
(when property?
(property-component/property-config page page (assoc opts
:inline-text component-block/inline-text)))])]
(when (and class-or-property?
(not (db-property-handler/block-has-viewable-properties? page))
(not config/publishing?)
(empty? (:properties (:block/schema page))))
[:a.fade-link.flex.flex-row.items-center.gap-1.text-sm
{:on-click #(swap! *show-page-properties? not)}
(ui/icon (if @*show-page-properties?
"arrow-narrow-left"
"arrow-narrow-right"))
(if @*show-page-properties?
"Back"
"Edit page properties")])]))
(rum/defc page-configure
[page *hover? *configuring?]
(when (or @*hover? (and config/publishing? (some #{"class" "property"} (:block/type page))))
(let [toggle-fn' (fn [toggle-fn]
(fn []
(toggle-fn)
(reset! *configuring? true)))]
(ui/dropdown
(fn [{:keys [toggle-fn]}]
[:a.fade-link.flex.flex-row.items-center
{:on-click (toggle-fn' toggle-fn)}
[:div.mr-1.text-sm (if-let [block-type (and config/publishing?
(some #{"class" "property"} (:block/type page)))]
(str "More info on this " block-type)
"Configure")]])
(fn [{:keys [toggle-fn]}]
(page-configure-inner
page
(fn []
(reset! *configuring? false)
(reset! *hover? false))
{:toggle-fn toggle-fn}))
{:modal-class (util/hiccup->class
"origin-top-right.absolute.left-0.mt-2.rounded-md.shadow-lg")}))))
page-opts {:configure? true}]
(when (nil? mode)
(reset! *mode (cond
property? :property
class? :class
:else :page)))
[:div.flex.flex-col.gap-1
(if (= mode :property)
(property-component/property-config page page {:inline-text component-block/inline-text})
[:<>
(when (= mode :class)
(class-component/configure page {:show-title? false}))
(when-not config/publishing? (tags-row page))
(when-not config/publishing? (icon-row page))
(page-properties page (assoc page-opts :mode mode))])]))
(rum/defc page-properties-react < rum/reactive
[page* page-opts]
@ -197,23 +158,96 @@
(some #{"class" "property"} (:block/type page)))
(page-properties page page-opts))))
(rum/defc page-tags <
[page tags-property *hover? *configuring?]
(let [toggle-fn' (fn [toggle-fn]
(fn []
(toggle-fn)
(swap! *configuring? not)))]
(ui/dropdown
(fn [{:keys [toggle-fn]}]
[:a.fade-link.flex.flex-row.items-center
{:on-click (toggle-fn' toggle-fn)}
[:div.ml-1.text-sm "Set tags"]])
(fn [{:keys [toggle-fn]}]
(pv/property-value page tags-property nil {:on-chosen (toggle-fn' toggle-fn)
:dropdown? false}))
{:modal-class (util/hiccup->class
"origin-top-right.absolute.left-0.mt-2.rounded-md.shadow-lg")
:on-toggle (fn [value]
(when (false? value)
(reset! *configuring? false)
(reset! *hover? false)))})))
(rum/defc mode-switch < rum/reactive
[types *mode]
(let [current-mode (rum/react *mode)
property? (contains? types "property")
class? (contains? types "class")
modes (->
(cond
(and property? class?)
["Property" "Class"]
property?
["Property"]
class?
["Class"]
:else
[])
(conj "Page"))]
[:div.flex.flex-row.items-center.gap-1
(for [mode modes]
(let [mode' (keyword (string/lower-case mode))
selected? (= mode' current-mode)]
(shui-ui/button {:variant (if selected? :outline :ghost) :size :sm
:on-click (if config/publishing?
util/stop-propagation
(fn [e]
(util/stop-propagation e)
(reset! *mode mode')))}
mode)))]))
(rum/defcs page-info < rum/reactive
(rum/local false ::hover?)
(rum/local nil ::mode)
{:init (if config/publishing?
(fn [state]
(let [page* (first (:rum/args state))
page (db/sub-block (:db/id page*))]
(assoc state
::collapsed?
(atom (not (seq (set/intersection #{"class" "property"} (:block/type page))))))))
(fn [state]
(let [page (first (:rum/args state))
properties (:block/properties page)]
(assoc state ::collapsed? (atom (empty? properties))))))}
[state page *hover-title?]
(let [page (db/sub-block (:db/id page))
*collapsed? (::collapsed? state)
*hover? (::hover? state)
*mode (::mode state)
types (:block/type page)
hover-title? (rum/react *hover-title?)
collapsed? (rum/react *collapsed?)
has-tags? (seq (:block/tags page))
hover-or-expanded? (or @*hover? hover-title? (not collapsed?))]
(when (if config/publishing?
;; Since publishing is read-only, hide this component if it has no info to show
;; as it creates a fair amount of empty vertical space
(or has-tags? (some? types))
true)
[:div.page-info {:on-mouse-over #(reset! *hover? true)
:on-mouse-leave #(reset! *hover? false)}
(when (or hover-or-expanded? has-tags?)
[:div.fade-in.p-2 (cond-> {}
(or @*hover? (not collapsed?))
(assoc :class "border rounded"))
[:div.info-title.cursor {:on-click
(if config/publishing?
(fn [_]
(when (seq (set/intersection #{"class" "empty"} types))
(swap! *collapsed? not)))
#(swap! *collapsed? not))}
[:div.flex.flex-row.items-center.gap-2.justify-between
[:div.flex.flex-row.items-center.gap-2
(if collapsed?
[:<>
(shui-ui/button {:variant :ghost :size :sm :class "fade-link"}
(ui/icon "tags"))
[:div {:on-click util/stop-propagation}
(tags page)]]
[:div.flex.flex-row.items-center.gap-1
(shui-ui/button {:variant :ghost :size :sm :class "fade-link"}
(ui/icon "info-circle"))
[:a.text-sm.font-medium.fade-link
"Configure:"]
(mode-switch types *mode)])]
(when (or @*hover? (not collapsed?))
(shui-ui/button
{:variant :ghost :size :sm :class "fade-link"}
(ui/icon (if collapsed?
"chevron-down"
"chevron-up"))))]]
(when-not collapsed?
[:div.py-2.px-4
(page-configure page *mode)])])])))

View File

@ -177,7 +177,8 @@
[:button.flex {:on-click #(when-not disabled? (toggle-fn))}
(if icon-value
(icon icon-value)
[:span.bullet-container.cursor [:span.bullet]])])
[:div.opacity-50.text-sm
"Empty"])])
(if config/publishing?
(constantly [])
(fn [{:keys [toggle-fn]}]

View File

@ -10,7 +10,6 @@
[frontend.components.reference :as reference]
[frontend.components.scheduled-deadlines :as scheduled]
[frontend.components.icon :as icon-component]
[frontend.components.property.value :as pv]
[frontend.components.db-based.page :as db-page]
[frontend.handler.property.util :as pu]
[frontend.handler.db-based.property :as db-property-handler]
@ -312,24 +311,20 @@
(rum/defcs ^:large-vars/cleanup-todo page-title < rum/reactive
(rum/local false ::edit?)
(rum/local "" ::input-value)
(rum/local false ::hover?)
(rum/local false ::configuring?)
{:init (fn [state]
(let [page-name (first (:rum/args state))
original-name (:block/original-name (db/entity [:block/name (util/page-name-sanity-lc page-name)]))
*title-value (atom original-name)]
(assoc state ::title-value *title-value)))}
[state page-name {:keys [fmt-journal? preview?]}]
[state page-name {:keys [fmt-journal? preview? *hover?]}]
(when page-name
(let [page (when page-name (db/entity [:block/name page-name]))
page (db/sub-block (:db/id page))
title (:block/original-name page)]
(when title
(let [icon (pu/lookup (:block/properties page) :icon)
*hover? (::hover? state)
*title-value (get state ::title-value)
*edit? (get state ::edit?)
*configuring? (::configuring? state)
*input-value (get state ::input-value)
repo (state/get-current-repo)
hls-page? (pdf-utils/hls-file? title)
@ -341,12 +336,10 @@
(date/journal-title->custom-format title)
title))
old-name (or title page-name)
db-based? (config/db-based-graph? repo)
tags-property (db/entity [:block/name "tags"])]
db-based? (config/db-based-graph? repo)]
[:div.ls-page-title.flex.flex-1.flex-row.flex-wrap.w-full.relative.items-center.gap-2
{:on-mouse-over #(reset! *hover? true)
:on-mouse-out #(when-not @*configuring?
(reset! *hover? false))}
:on-mouse-out #(reset! *hover? false)}
(when icon
[:div.page-icon {:on-mouse-down util/stop-propagation}
(if (and (map? icon) db-based?)
@ -358,66 +351,61 @@
(:block/uuid page)
{:properties {icon-property-id icon}})))})
icon)])
[:div.flex.flex-1.flex-row.flex-wrap.items-center.gap-4
[:h1.page-title.flex-1.cursor-pointer.gap-1
{:class (when-not whiteboard-page? "title")
:on-mouse-down (fn [e]
(when (util/right-click? e)
(state/set-state! :page-title/context {:page page-name})))
:on-click (fn [e]
(when-not (= (.-nodeName (.-target e)) "INPUT")
(.preventDefault e)
(if (gobj/get e "shiftKey")
(when-let [page (db/pull repo '[*] [:block/name page-name])]
(state/sidebar-add-block!
repo
(:db/id page)
:page))
(when (and (not hls-page?)
(not fmt-journal?)
(not config/publishing?)
(not (and (contains? (:block/type page) "property")
(contains? db-property/built-in-properties-keys-str page-name))))
(reset! *input-value (if untitled? "" old-name))
(reset! *edit? true)))))}
[:h1.page-title.flex-1.cursor-pointer.gap-1
{:class (when-not whiteboard-page? "title")
:on-mouse-down (fn [e]
(when (util/right-click? e)
(state/set-state! :page-title/context {:page page-name})))
:on-click (fn [e]
(when-not (= (.-nodeName (.-target e)) "INPUT")
(.preventDefault e)
(if (gobj/get e "shiftKey")
(when-let [page (db/pull repo '[*] [:block/name page-name])]
(state/sidebar-add-block!
repo
(:db/id page)
:page))
(when (and (not hls-page?)
(not fmt-journal?)
(not config/publishing?)
(not (and (contains? (:block/type page) "property")
(contains? db-property/built-in-properties-keys-str page-name))))
(reset! *input-value (if untitled? "" old-name))
(reset! *edit? true)))))}
(if @*edit?
(page-title-editor page {:*title-value *title-value
:*edit? *edit?
:*input-value *input-value
:page-name page-name
:old-name old-name
:untitled? untitled?
:whiteboard-page? whiteboard-page?
:preview? preview?})
[:span.title.block
{:on-click (fn []
(when (and (state/home?) (not preview?))
(route-handler/redirect-to-page! page-name)))
:data-value @*input-value
:data-ref page-name
:style {:opacity (when @*edit? 0)}}
(let [nested? (and (string/includes? title page-ref/left-brackets)
(string/includes? title page-ref/right-brackets))]
(cond untitled? [:span.opacity-50 (t :untitled)]
nested? (component-block/map-inline {} (gp-mldoc/inline->edn title (mldoc/get-default-config
(:block/format page))))
:else title))])]
(when (and db-based? (seq (:block/tags page)))
[:div.page-tags.ml-4
(pv/property-value page tags-property (map :block/uuid (:block/tags page))
{:page-cp (fn [config page]
(component-block/page-cp (assoc config :tag? true) page))})])]
(if @*edit?
(page-title-editor page {:*title-value *title-value
:*edit? *edit?
:*input-value *input-value
:page-name page-name
:old-name old-name
:untitled? untitled?
:whiteboard-page? whiteboard-page?
:preview? preview?})
[:span.title.block
{:on-click (fn []
(when (and (state/home?) (not preview?))
(route-handler/redirect-to-page! page-name)))
:data-value @*input-value
:data-ref page-name
:style {:opacity (when @*edit? 0)}}
(let [nested? (and (string/includes? title page-ref/left-brackets)
(string/includes? title page-ref/right-brackets))]
(cond untitled? [:span.opacity-50 (t :untitled)]
nested? (component-block/map-inline {} (gp-mldoc/inline->edn title (mldoc/get-default-config
(:block/format page))))
:else title))])]
(when (and db-based? (not whiteboard-page?))
[:div.absolute.bottom-2.left-0
[:div.page-add-tags.flex.flex-row.items-center.flex-wrap.gap-2.ml-2
(when (and (empty? (:block/tags page)) @*hover? (not config/publishing?))
(db-page/page-tags page tags-property *hover? *configuring?))
;; (when (and db-based? (not whiteboard-page?))
;; [:div.absolute.bottom-2.left-0
;; [:div.page-add-tags.flex.flex-row.items-center.flex-wrap.gap-2.ml-2
;; (when (and (empty? (:block/tags page)) @*hover? (not config/publishing?))
;; (db-page/page-tags page tags-property *hover? *configuring?))
(when (or (some #(contains? #{"class" "property"} %) (:block/type page))
(not (db-property-handler/block-has-viewable-properties? page)))
(db-page/page-configure page *hover? *configuring?))]])])))))
;; (when (or (some #(contains? #{"class" "property"} %) (:block/type page))
;; (not (db-property-handler/block-has-viewable-properties? page)))
;; (db-page/page-configure page *hover? *configuring?))]])
])))))
(defn- page-mouse-over
[e *control-show? *all-collapsed?]
@ -472,6 +460,7 @@
(rum/local false ::all-collapsed?)
(rum/local false ::control-show?)
(rum/local nil ::current-page)
(rum/local false ::hover-title?)
[state {:keys [repo page-name preview? sidebar?] :as option}]
(when-let [path-page-name (get-path-page-name state page-name)]
(let [current-repo (state/sub :git/current-repo)
@ -524,13 +513,18 @@
(when (and (not whiteboard?) original-name)
(page-title page-name {:journal? journal?
:fmt-journal? fmt-journal?
:preview? preview?})))
:preview? preview?
:*hover? (::hover-title? state)})))
(when (not config/publishing?)
(when config/lsp-enabled?
[:div.flex.flex-row
(plugins/hook-ui-slot :page-head-actions-slotted nil)
(plugins/hook-ui-items :pagebar)]))])
(when db-based?
[:div.pb-4
(db-page/page-info page (::hover-title? state))])
[:div
(when (and block? (not sidebar?) (not whiteboard?))
(let [config {:id "block-parent"

View File

@ -239,9 +239,8 @@
.ls-page-title {
@apply rounded-sm;
padding: 5px 8px;
padding-bottom: 2rem;
margin: 0 -6px 12px -6px;
padding: 5px 8px 12px 8px;
margin: 0 -6px;
&.title {
margin-bottom: 12px;
@ -408,3 +407,8 @@ html.is-native-ios {
.ring-none {
@apply focus:ring-0 focus:ring-offset-0;
}
.page-info {
min-height: 46px;
margin-left: -21px;
}

View File

@ -1,6 +1,5 @@
.property-configure {
min-width: 32rem;
padding: 2px;
.form-input, .form-select {
line-height: 1rem;

View File

@ -269,7 +269,7 @@
e
(content/page-title-custom-context-menu-content page-name))
(state/set-state! :page-title/context nil))}
(page/page-title page-name {:*configure-show? (atom false)})]
(page/page-title page-name {:*hover? (atom false)})]
[:div.whiteboard-page-refs
(references-count page-name

View File

@ -140,8 +140,8 @@
[repo]
(if @*publishing?
(p/let [^object DB (.-DB ^object (.-oo1 ^object @*sqlite))
db (new DB "/db.sqlite" "ct")
search-db (new DB "/search-db.sqlite" "ct")]
db (new DB "/db.sqlite" "c")
search-db (new DB "/search-db.sqlite" "c")]
[db search-db])
(p/let [^js pool (<get-opfs-pool repo)
capacity (.getCapacity pool)

View File

@ -811,7 +811,7 @@
(defmethod handle :class/configure [[_ page]]
(state/set-modal!
#(vector :<>
(class-component/configure page)
(class-component/configure page {})
(db-page/page-properties page {:configure? true}))
{:id :page-configure
:label "page-configure"

View File

@ -395,7 +395,6 @@
:linked-references/filter-includes "Incluye: "
:linked-references/filter-search "Buscar en las páginas vinculadas"
:linked-references/reference-count (fn [filtered-count total] (str (when filtered-count (str filtered-count " de ")) total (if (= total 1) " Referencia vinculada" " Referencias vinculadas")))
:linked-references/unexpected-error "Referencias vinculadas: Error inesperado. Reindexa tu gráfico primero."
:notification/clear-all "Limpiar todo"
:on-boarding/add-graph "Añadir grafo"
:on-boarding/command-palette-quick-tour "Tour rápido para acostumbrarse"

View File

@ -776,7 +776,6 @@
:linked-references/filter-heading "Filter"
:linked-references/filter-includes "Inkluderer: "
:linked-references/reference-count (fn [filtered-count total] (str (when filtered-count (str filtered-count " av ")) total (if (= total 1) " Lenket Referanse" " Lenkede Referanser")))
:linked-references/unexpected-error "Lenkede Referanser: Uventet feil. Vennligst re-indekser din graf først."
:pdf/auto-open-context-menu "Auto-åpne kontekstmeny for valg"
:unlinked-references/reference-count (fn [total] (str total (if (= total 1) " Ulenket Referanse" " Ulenkede Referanser")))
:whiteboard/reference-count (fn [refs-count] (if (= refs-count 1) "Referanse" "Referanser"))}

View File

@ -1,12 +1,9 @@
(ns frontend.handler.export-test
(:require [cljs.test :refer [are async deftest is use-fixtures]]
[clojure.edn :as edn]
(:require [cljs.test :refer [are async deftest use-fixtures]]
[clojure.string :as string]
[frontend.handler.export :as export]
[frontend.handler.export.text :as export-text]
[frontend.state :as state]
[frontend.test.helper :as test-helper :include-macros true :refer [deftest-async]]
[logseq.db.frontend.default :as default-db]
[promesa.core :as p]))
(def test-files

View File

@ -1,8 +1,7 @@
(ns frontend.worker.rtc.asset-sync-effects-test
"This ns include tests abouts asset-sync with other components.
These tests need to start the asset-sync-loop."
(:require [cljs.core.async :as async :refer [<! >! go timeout]]
[clojure.test :as t :refer [deftest is use-fixtures]]
(:require [clojure.test :as t :refer [deftest is use-fixtures]]
[frontend.test.helper :include-macros true :as test-helper]
[frontend.worker.rtc.fixture :as rtc-fixture]
[spy.core :as spy]))

View File

@ -18,4 +18,4 @@ fom = "fom"
tne = "tne"
Damon = "Damon"
[files]
extend-exclude = ["resources/*", "src/resources/*", "scripts/resources/*"]
extend-exclude = ["resources/*", "src/resources/*", "scripts/resources/*", "e2e-tests/plugin/lsplugin.user.js"]