enhance: page properties ux

This commit is contained in:
Tienson Qin
2023-08-08 21:04:20 +08:00
parent de6669fce0
commit bf73045891
7 changed files with 153 additions and 187 deletions

View File

@@ -27,50 +27,9 @@
[title]
(let [;; Don't edit the journal title
page (string/lower-case title)
repo (state/sub :git/current-repo)
today? (= (string/lower-case title)
(string/lower-case (date/journal-name)))
page-entity (db/pull [:block/name (util/page-name-sanity-lc title)])
data-page-tags (when (seq (:block/tags page-entity))
(let [page-names (model/get-page-names-by-ids (map :db/id (:block/tags page)))]
(text-util/build-data-value page-names)))]
[:div.flex-1.journal.page (cond-> {}
data-page-tags
(assoc :data-page-tags data-page-tags))
(ui/foldable
[:a.initial-color.title.journal-title
{:href (rfe/href :page {:name page})
:on-mouse-down (fn [e]
(when (util/right-click? e)
(state/set-state! :page-title/context {:page page})))
:on-click (fn [e]
(when (gobj/get e "shiftKey")
(when-let [page page-entity]
(state/sidebar-add-block!
(state/get-current-repo)
(:db/id page)
:page))
(.preventDefault e)))}
[:h1.title
(gp-util/capitalize-all title)]]
(if today?
(blocks-cp repo page)
(ui/lazy-visible
(fn [] (blocks-cp repo page))
{:debug-id (str "journal-blocks " page)}))
{})
(page/today-queries repo today? false)
(when today?
(scheduled/scheduled-and-deadlines page))
(rum/with-key
(reference/references title)
(str title "-refs"))]))
repo (state/sub :git/current-repo)]
(page/page {:repo repo
:page-name page})))
(rum/defc journals < rum/reactive
[latest-journals]

View File

@@ -287,11 +287,13 @@
(rum/defcs page-title < rum/reactive
(rum/local false ::edit?)
(rum/local "" ::input-value)
(rum/local false ::hover?)
{:init (fn [state]
(assoc state ::title-value (atom (nth (:rum/args state) 2))))}
[state page-name icon title _format fmt-journal?]
[state page-name icon title {:keys [fmt-journal? *configure-show? built-in-property?]}]
(when title
(let [page (when page-name (db/entity [:block/name page-name]))
*hover? (::hover? state)
*title-value (get state ::title-value)
*edit? (get state ::edit?)
*input-value (get state ::input-value)
@@ -304,50 +306,70 @@
(if fmt-journal?
(date/journal-title->custom-format title)
title))
old-name (or title page-name)]
[:h1.page-title.flex.cursor-pointer.gap-1.w-full
{: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 (= "property" (:block/type page))
(contains? gp-property/db-built-in-properties-keys-str page-name))))
(reset! *input-value (if untitled? "" old-name))
(reset! *edit? true)))))}
(when (not= icon "") [:span.page-icon icon])
[:div.page-title-sizer-wrapper.relative
(when @*edit?
(page-title-editor {:*title-value *title-value
:*edit? *edit?
:*input-value *input-value
:title title
:page-name page-name
:old-name old-name
:untitled? untitled?
:whiteboard-page? whiteboard-page?}))
[:span.title.block
{: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 @*edit? [:span {:style {:white-space "pre"}} (rum/react *input-value)]
untitled? [:span.opacity-50 (t :untitled)]
nested? (component-block/map-inline {} (gp-mldoc/inline->edn title (gp-mldoc/default-config
(:block/format page))))
:else title))]]])))
old-name (or title page-name)
db-based? (config/db-based-graph? repo)]
[:div.ls-page-title.flex-1.flex-row.w-full.relative
{:on-mouse-over #(reset! *hover? true)
:on-mouse-out #(reset! *hover? false)}
[:h1.page-title.flex.cursor-pointer.gap-1.w-full
{: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 (= "property" (:block/type page))
(contains? gp-property/db-built-in-properties-keys-str page-name))))
(reset! *input-value (if untitled? "" old-name))
(reset! *edit? true)))))}
(when (not= icon "") [:span.page-icon icon])
[:div.page-title-sizer-wrapper.relative
(when @*edit?
(page-title-editor {:*title-value *title-value
:*edit? *edit?
:*input-value *input-value
:title title
:page-name page-name
:old-name old-name
:untitled? untitled?
:whiteboard-page? whiteboard-page?}))
[:span.title.block
{:on-click (fn []
(when (state/home?)
(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 @*edit? [:span {:style {:white-space "pre"}} (rum/react *input-value)]
untitled? [:span.opacity-50 (t :untitled)]
nested? (component-block/map-inline {} (gp-mldoc/inline->edn title (gp-mldoc/default-config
(:block/format page))))
:else title))]]]
(when (and @*hover?
db-based?
(not built-in-property?)
(not @*edit?)
(not (seq (:block/properties page)))
(not (seq (:block/alias page)))
(not (seq (:block/tags page))))
[:div.absolute.bottom-2.left-0
[:div.flex.flex-row.items-center.flex-wrap.ml-2
[:a.fade-link.flex.flex-row.items-center
{:on-click #(reset! *configure-show? true)}
(ui/icon "plus" {:size 14})
[:div.ml-1.text-sm "Add property"]]]])])))
(defn- page-mouse-over
[e *control-show? *all-collapsed?]
@@ -378,11 +400,56 @@
"control-show cursor-pointer" "control-hide")}
(ui/rotating-arrow @*all-collapsed?)]])
(rum/defcs configure < rum/reactive
[state page opts]
(let [page-id (:db/id page)
page (when page-id (db/sub-block page-id))
type (:block/type page)
properties-opts (merge {:selected? false
:page-configure? true}
opts)]
(when page
[:div.property-configure
[:div.grid.gap-4.p-1
(case type
"class"
[:div
[:div.structured-schema
;; properties
[:h2.text-lg.font-medium.mb-2 "Schema:"]
[:div.grid.gap-1
(let [edit-input-id (str "edit-block-" (:block/uuid page) "-schema")]
(component-block/db-properties-cp
{:editor-box editor/box}
page
edit-input-id
(assoc properties-opts :class-schema? true)))]]
(when (seq (:block/properties page))
[:div.my-4
[:div.grid.gap-1
(let [edit-input-id (str "edit-block-" (:block/uuid page))]
(component-block/db-properties-cp
{:editor-box editor/box}
page
edit-input-id
properties-opts))]])]
[:div
(let [edit-input-id (str "edit-block-" (:block/uuid page))]
[:div
(component-block/db-properties-cp
{:editor-box editor/box}
page
edit-input-id
properties-opts)])])]])))
;; A page is just a logical block
(rum/defcs ^:large-vars/cleanup-todo page < rum/reactive
(rum/local false ::all-collapsed?)
(rum/local false ::control-show?)
(rum/local nil ::current-page)
(rum/local false ::configure-show?)
[state {:keys [repo page-name] :as option}]
(when-let [path-page-name (or page-name
(get-block-uuid-by-block-route-name state)
@@ -391,14 +458,14 @@
(state/get-current-page))]
(let [current-repo (state/sub :git/current-repo)
repo (or repo current-repo)
*configure-show? (::configure-show? state)
page-name (util/page-name-sanity-lc path-page-name)
block-id (parse-uuid page-name)
block? (boolean block-id)
format (let [page (if block-id
(:block/name (:block/page (db/entity [:block/uuid block-id])))
page-name)]
(db/get-page-format page))
journal? (db/journal-page? page-name)
db-based? (config/db-based-graph? repo)
built-in-property? (and (= "property" (:block/type page))
(contains? gp-property/db-built-in-properties-keys-str page-name))
fmt-journal? (boolean (date/journal-title->int page-name))
sidebar? (:sidebar? option)
whiteboard? (:whiteboard? option) ;; in a whiteboard portal shape?
@@ -447,13 +514,18 @@
(page-mouse-leave e *control-show?))}
(page-blocks-collapse-control title *control-show? *all-collapsed?)])
(when-not whiteboard?
[:div.ls-page-title.flex-1.flex-row.w-full
(page-title page-name icon title format fmt-journal?)])
(page-title page-name icon title {:fmt-journal? fmt-journal?
:*configure-show? *configure-show?
:built-in-property? built-in-property?}))
(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 (and @*configure-show? db-based? (not built-in-property?))
(configure page {:*configure-show? *configure-show?}))
[:div
(when (and block? (not sidebar?) (not whiteboard?))
(let [config {:id "block-parent"
@@ -468,7 +540,7 @@
(or (seq (:block/properties page))
(seq (:block/alias page))
(seq (:block/tags page))))
[:div.page-properties.p-2.mb-4
[:div.p-2.mb-4
(let [edit-input-id (str "edit-block-" (:block/uuid page) "-schema")]
(component-block/db-properties-cp
{:editor-box editor/box}
@@ -1155,60 +1227,3 @@
:total total-items
:per-page per-page-num
:on-change #(to-page %))]])]))
(rum/defcs configure < rum/reactive
[state page]
(let [page-id (:db/id page)
page (when page-id (db/sub-block page-id))
type (:block/type page)
class? (= "class" type)
journal? (:block/journal? page)]
(when page
[:div.page-configure
[:h1.title "Configure page"]
[:div.grid.gap-4.p-1
(case type
"class"
[:div
[:div.structured-schema
;; properties
[:h2.text-lg.font-medium.mb-2 "Schema properties:"]
[:div.grid.gap-1
(let [edit-input-id (str "edit-block-" (:block/uuid page) "-schema")]
(component-block/db-properties-cp
{:editor-box editor/box}
page
edit-input-id
{:selected? false
:page-configure? true
:class-schema? true}))]]
(when (seq (:block/properties page))
[:div.my-4
[:h2.text-lg.font-medium.mb-2 "Page properties:"]
[:div.grid.gap-1
(let [edit-input-id (str "edit-block-" (:block/uuid page))]
(component-block/db-properties-cp
{:editor-box editor/box}
page
edit-input-id
{:selected? false
:page-configure? true}))]])]
[:div
[:h2.text-lg.font-medium.mb-2 "Properties:"]
(let [edit-input-id (str "edit-block-" (:block/uuid page))]
[:div
(component-block/db-properties-cp
{:editor-box editor/box}
page
edit-input-id
{:selected? false
:page-configure? true})])])]
(when config/dev?
[:div {:style {:max-width 900}}
[:hr]
[:p "Debug data:"]
[:pre (util/pp-str page)]])])))

View File

@@ -84,14 +84,7 @@
(contains? gp-property/db-built-in-properties-keys-str page-name))]
(when (and page (not block?))
(->>
[(when (and (not config/publishing?)
(config/db-based-graph? repo)
(not built-in-property?))
{:title (t :page/configure)
:options {:on-click
(fn []
(state/pub-event! [:page/configure page]))}})
(when-not config/publishing?
[(when-not config/publishing?
{:title (if favorited?
(t :page/unfavorite)
(t :page/add-to-favorites))

View File

@@ -9,14 +9,12 @@
[frontend.handler.notification :as notification]
[frontend.db :as db]
[frontend.db.model :as model]
[frontend.config :as config]
[rum.core :as rum]
[frontend.state :as state]
[frontend.mixins :as mixins]
[clojure.string :as string]
[goog.dom :as gdom]
[frontend.search :as search]
[frontend.components.svg :as svg]
[frontend.modules.shortcut.core :as shortcut]
[frontend.components.select :as select]
[logseq.graph-parser.property :as gp-property]
@@ -60,7 +58,7 @@
(reset! (::property-name state) (:block/original-name property))
(reset! (::property-schema state) (:block/schema property))
state))}
[state repo property]
[state repo property {:keys [toggle-fn]}]
(let [*property-name (::property-name state)
*property-schema (::property-schema state)
built-in-property? (contains? gp-property/db-built-in-properties-keys-str (:block/original-name property))
@@ -122,18 +120,14 @@
(when-not built-in-property?
(ui/button
"Save"
:on-click (fn []
:on-click (fn [e]
(util/stop e)
(property-handler/update-property!
repo (:block/uuid property)
{:property-name @*property-name
:property-schema @*property-schema})
(state/close-modal!))))]
(when config/dev?
[:div {:style {:max-width 900}}
[:hr]
[:p "Debug data:"]
[:pre (util/pp-str property)]])]]))
(state/close-modal!)
(when toggle-fn (toggle-fn)))))]]]))
(defn- exit-edit-property
[]
@@ -282,7 +276,7 @@
[block property value {:keys [inline-text page-cp block-cp
editor-id dom-id row?
editor-box editor-args
editing? editing-atom
editing? editing-atom *configure-show?
blocks-container-id]}]
(let [property (model/sub-block (:db/id property))
multiple-values? (= :many (:cardinality (:block/schema property)))
@@ -290,7 +284,9 @@
editing? (or editing? (state/sub [:editor/editing? editor-id]))
repo (state/get-current-repo)
type (:type (:block/schema property))
select-opts {:on-chosen (fn [] (when editing-atom (reset! editing-atom false)))}]
select-opts {:on-chosen (fn []
(when *configure-show? (reset! *configure-show? false))
(when editing-atom (reset! editing-atom false)))}]
(case type
:date
(date-picker block property value)
@@ -396,7 +392,7 @@
(db-property/upsert-property! repo property-name {:type :default} {})
;; configure new property
(when-let [property (get-property-from-db property-name)]
(state/set-sub-modal! #(property-config repo property)))))
(state/set-sub-modal! #(property-config repo property {})))))
(do (notification/show! "This is an invalid property name. A property name cannot start with page reference characters '#' or '[['." :error)
(exit-edit-property))))))
@@ -422,9 +418,7 @@
[:div.col-span-1 @*property-key]
[:div.col-span-3.flex.flex-row
(when (and property (not class-schema?))
(property-scalar-value entity property @*property-value (assoc opts :editing? true)))
[:a.close {:on-mouse-down exit-edit-property}
svg/close]]])
(property-scalar-value entity property @*property-value (assoc opts :editing? true)))]])
[:div.ls-property-add.h-6
(select/select {:items (map (fn [x] {:value x}) properties)
@@ -489,9 +483,9 @@
;; default property icon
(ui/icon "circle-dotted" {:size 16}))
[:div.ml-1 (:block/original-name property)]]])
(fn [{:keys [_toggle-fn]}]
(fn [{:keys [toggle-fn]}]
[:div.p-8
(property-config repo property)])
(property-config repo property {:toggle-fn toggle-fn})])
{:modal-class (util/hiccup->class
"origin-top-right.absolute.left-0.rounded-md.shadow-lg")})))
@@ -608,7 +602,6 @@
alias (set (map :block/uuid (:block/alias block)))
alias-properties (when (seq alias)
[[(:block/uuid (db/entity [:block/name "alias"])) alias]])
new-property? (= edit-input-id (state/sub :ui/new-property-input-id))
class-properties (->> (:block/tags block)
(mapcat (fn [tag]
(when (= "class" (:block/type tag))
@@ -618,14 +611,19 @@
[id nil])))
built-in-properties (set/difference
(set (map name gp-property/db-built-in-properties-keys))
#{"alias"})
#{"alias" "tags"})
properties (->> (concat (seq alias-properties)
(seq properties)
class-properties)
(util/distinct-by first)
(remove (fn [[k _v]]
(when (uuid? k)
(contains? built-in-properties (:block/name (db/entity [:block/uuid k])))))))]
(contains? built-in-properties (:block/name (db/entity [:block/uuid k])))))))
new-property? (or
(and (:*configure-show? opts)
@(:*configure-show? opts)
(empty? properties))
(= edit-input-id (state/sub :ui/new-property-input-id)))]
(when-not (and (empty? properties)
(not new-property?)
(not (:page-configure? opts)))

View File

@@ -1,3 +1,8 @@
.property-configure {
min-width: 600px;
max-width: 800px;
}
.property-value-content {
@apply px-1 rounded-sm;
cursor: text;

View File

@@ -982,9 +982,6 @@
(when-let [blocks (and block (db-model/get-block-immediate-children (state/get-current-repo) (:block/uuid block)))]
(editor-handler/toggle-blocks-as-own-order-list! blocks)))
(defmethod handle :page/configure [[_ page]]
(state/set-modal! #(page/configure page)))
(defn run!
[]
(let [chan (state/get-events-chan)]

View File

@@ -169,7 +169,6 @@
:page/open-backup-directory "Open page backups directory"
:page/make-private "Make it private"
:page/delete "Delete page"
:page/configure "Configure page"
:page/add-to-favorites "Add to Favorites"
:page/unfavorite "Unfavorite page"
:page/show-journals "Show journals"