feat: structured pages

This commit is contained in:
Tienson Qin
2023-07-10 03:01:40 +08:00
parent 23a64d6061
commit 3820cb7ff6
9 changed files with 165 additions and 126 deletions

View File

@@ -1896,22 +1896,6 @@
:html (set-priority block priority)}
(priority-text priority))))
(defn block-tags-cp
[{:block/keys [pre-block? tags] :as _block}]
(when (and (not pre-block?)
(seq tags))
(->elem
:span
{:class "block-tags"}
(mapv (fn [tag]
(when-let [page (db/entity (:db/id tag))]
(let [tag (:block/name page)]
[:a.tag.mx-1 {:data-ref tag
:key (str "tag-" (:db/id tag))
:href (rfe/href :page {:name tag})}
(str "#" tag)])))
tags))))
(declare block-content)
(defn build-block-title
@@ -1930,7 +1914,6 @@
(marker-switch t))
marker-cp (marker-cp t)
priority (priority-cp t)
tags (block-tags-cp t)
bg-color (:background-color properties)
;; `heading-level` is for backward compatibility, will remove it in later releases
heading-level (:block/heading-level t)
@@ -2001,8 +1984,6 @@
(when (= block-type :whiteboard-shape) [:span.mr-1 (ui/icon "whiteboard-element" {:extension? true})]))
[[:span.opacity-50 "Click here to start writing, type '/' to see all the commands."]])
[tags]
;; highlight ref block (area)
(when area? [(hl-ref)])))))))

View File

@@ -233,10 +233,10 @@
[block property value {:keys [inline-text page-cp block-cp
editor-id dom-id
editor-box editor-args
new-item?]}]
new-item? editing?]}]
(let [multiple-values? (= :many (:cardinality (:block/schema property)))
editor-id (or editor-id (str "ls-property-" (:db/id block) "-" (:db/id property)))
editing? (state/sub [:editor/editing? editor-id])
editing? (or editing? (state/sub [:editor/editing? editor-id]))
repo (state/get-current-repo)
type (:type (:block/schema property))]
(when (or (not new-item?) editing?)
@@ -373,7 +373,7 @@
[:div.ls-property-add.grid.grid-cols-4.gap-1.flex.flex-row.items-center
(property-key-input entity *property-key *property-value *search?)
(when (and property (not (:class-schema? opts)))
(property-scalar-value entity property @*property-value opts))
(property-scalar-value entity property @*property-value (assoc opts :editing? true)))
[:a.close {:on-mouse-down exit-edit-property}
svg/close]]
@@ -414,20 +414,19 @@
(reset! *property-value nil))}
[:div.block {:style {:height 20
:width 20}}
[:a.add-button-link.block {:style {:margin-left -4}}
[:a.add-button-link.block.mt-1 {:style {:margin-left -4}}
(ui/icon "circle-plus")]]])))
(rum/defcs property-key
[state block property]
(let [repo (state/get-current-repo)]
[:div.relative
[:a.property-key
{:propertyid (:block/uuid property)
:blockid (:block/uuid block)
:title (str "Configure property: " (:block/original-name property))
:on-click (fn []
(state/set-sub-modal! #(property-config repo property)))}
(:block/original-name property)]]))
[:a
{:propertyid (:block/uuid property)
:blockid (:block/uuid block)
:title (str "Configure property: " (:block/original-name property))
:on-click (fn []
(state/set-sub-modal! #(property-config repo property)))}
(:block/original-name property)]))
(rum/defcs multiple-value-item < (rum/local false ::show-close?)
[state entity property items item {:keys [dom-id editor-id
@@ -440,7 +439,7 @@
editing? (state/sub [:editor/editing? editor-id])]
[:div.flex.flex-1.flex-row {:on-mouse-over #(reset! *show-close? true)
:on-mouse-out #(reset! *show-close? false)}
(property-scalar-value entity property item opts)
(property-scalar-value entity property item (assoc opts :editing? editing?))
(when (and (or (not new-item?) editing?)
@*show-close?
(seq items))
@@ -514,7 +513,16 @@
(rum/defcs properties-area < rum/reactive
[state block properties properties-text-values edit-input-id opts]
(let [repo (state/get-current-repo)
new-property? (= edit-input-id (state/sub :ui/new-property-input-id))]
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))
(let [e (db/entity (:db/id tag))]
(:properties (:block/schema e)) ))))
(map (fn [id]
[id nil])))
properties (->> (concat (seq properties) class-properties)
(util/distinct-by first))]
(when-not (and (empty? properties)
(not new-property?)
(not (:page-configure? opts)))
@@ -522,22 +530,21 @@
(when (:selected? opts)
{:class "select-none"})
(when (seq properties)
[:div.grid.gap-1
(for [[prop-uuid-or-built-in-prop v] properties]
(let [v (get properties-text-values prop-uuid-or-built-in-prop v)]
(if (uuid? prop-uuid-or-built-in-prop)
(when-let [property (db/sub-block (:db/id (db/entity [:block/uuid prop-uuid-or-built-in-prop])))]
[:div.grid.grid-cols-4.gap-1
[:div.property-key.col-span-1
(property-key block property)]
(if (:class-schema? opts)
[:div.property-description.col-span-3.font-light
(get-in property [:block/schema :description])]
[:div.property-value.col-span-3
(property-value block property v opts)])])
;; TODO: built in properties should have UUID and corresponding schema
;; builtin
[:div
[:a.mr-2 (str prop-uuid-or-built-in-prop)]
[:span v]])))])
(for [[prop-uuid-or-built-in-prop v] properties]
(let [v (get properties-text-values prop-uuid-or-built-in-prop v)]
(if (uuid? prop-uuid-or-built-in-prop)
(when-let [property (db/sub-block (:db/id (db/entity [:block/uuid prop-uuid-or-built-in-prop])))]
[:div.property-pair
[:div.property-key.col-span-1
(property-key block property)]
(if (:class-schema? opts)
[:div.property-description.col-span-3.font-light
(get-in property [:block/schema :description])]
[:div.property-value.col-span-3
(property-value block property v opts)])])
;; TODO: built in properties should have UUID and corresponding schema
;; builtin
[:div
[:a.mr-2 (str prop-uuid-or-built-in-prop)]
[:span v]]))))
(new-property repo block edit-input-id properties new-property? opts)])))

View File

@@ -9,6 +9,12 @@
}
.ls-properties-area {
@apply grid gap-1;
.property-pair {
@apply grid grid-cols-4 gap-1
}
.add-button-link {
opacity: 0.5;
}
@@ -47,6 +53,25 @@
.property-block-container {
margin-left: -1.5em;
}
.property-key a {
@apply whitespace-nowrap;
color: var(--ls-primary-text-color);
}
.property-key a:hover {
color: var(--ls-link-text-hover-color);
}
}
.block-main-container .ls-properties-area {
margin-top: 0.5em;
gap: 0;
.property-pair {
gap: 0;
}
}
input.simple-input {

View File

@@ -570,7 +570,7 @@
(rum/defc user-proxy-settings
[{:keys [type protocol host port] :as agent-opts}]
(ui/button [:span.flex.items-center
[:strong.pr-1
[:span.pr-1
(case type
"system" "System Default"
"direct" "Direct"

View File

@@ -1490,6 +1490,16 @@ independent of format as format specific heading characters are stripped"
{:id (str uuid)
:nonce (get-in properties [:logseq.tldraw.shape :nonce])}))))
(defn get-all-classes
[repo]
(d/q
'[:find [?name ...]
:where
[?page :block/type ?t]
[(= ?t "class")]
[?page :block/original-name ?name]]
(conn/get-db repo)))
(comment
;; For debugging
(defn get-all-blocks

View File

@@ -91,6 +91,40 @@
(let [tx (mapv (fn [page] [:db/retractEntity (:db/id page)]) orphaned-pages)]
(swap! txs-state (fn [state] (vec (concat state tx)))))))))
(defn- update-page-when-save-block
[txs-state block-entity m]
(when-let [e (:block/page block-entity)]
(let [m' (cond-> {:db/id (:db/id e)
:block/updated-at (util/time-ms)}
(not (:block/created-at e))
(assoc :block/created-at (util/time-ms)))
txs (if (or (:block/pre-block? block-entity)
(:block/pre-block? m))
(let [properties (:block/properties m)
alias (set (:alias properties))
tags (set (:tags properties))
alias (map (fn [p] {:block/name (util/page-name-sanity-lc p)}) alias)
tags (map (fn [p] {:block/name (util/page-name-sanity-lc p)}) tags)
deleteable-page-attributes {:block/alias alias
:block/tags tags
:block/properties properties
:block/properties-text-values (:block/properties-text-values m)}
;; Retract page attributes to allow for deletion of page attributes
page-retractions
(mapv #(vector :db/retract (:db/id e) %) (keys deleteable-page-attributes))]
(conj page-retractions (merge m' deleteable-page-attributes)))
[m'])]
(swap! txs-state into txs))))
(defn- remove-orphaned-refs-when-save
[txs-state block-entity m]
(when-not (config/db-based-graph? (state/get-current-repo))
(let [remove-self-page #(remove (fn [b]
(= (:db/id b) (:db/id (:block/page block-entity)))) %)
old-refs (remove-self-page (:block/refs block-entity))
new-refs (remove-self-page (:block/refs m))]
(remove-orphaned-page-refs! (:db/id block-entity) txs-state old-refs new-refs))))
;; -get-id, -get-parent-id, -get-left-id return block-id
;; the :block/parent, :block/left should be datascript lookup ref
@@ -148,15 +182,10 @@
(let [m (-> (:data this)
(dissoc :block/children :block/meta :block.temp/top? :block.temp/bottom?
:block/title :block/body :block/level)
(gp-util/remove-nils))
m (block-with-timestamps m)
other-tx (:db/other-tx m)
gp-util/remove-nils
block-with-timestamps)
id (:db/id (:data this))
block-entity (db/entity id)]
(when (seq other-tx)
(swap! txs-state (fn [txs]
(vec (concat txs other-tx)))))
(when id
;; Retract attributes to prepare for tx which rewrites block attributes
(swap! txs-state (fn [txs]
@@ -167,38 +196,17 @@
db-schema/retract-attributes)))))
;; Update block's page attributes
(when-let [e (:block/page block-entity)]
(let [m' (cond-> {:db/id (:db/id e)
:block/updated-at (util/time-ms)}
(not (:block/created-at e))
(assoc :block/created-at (util/time-ms)))
txs (if (or (:block/pre-block? block-entity)
(:block/pre-block? m))
(let [properties (:block/properties m)
alias (set (:alias properties))
tags (set (:tags properties))
alias (map (fn [p] {:block/name (util/page-name-sanity-lc p)}) alias)
tags (map (fn [p] {:block/name (util/page-name-sanity-lc p)}) tags)
deleteable-page-attributes {:block/alias alias
:block/tags tags
:block/properties properties
:block/properties-text-values (:block/properties-text-values m)}
;; Retract page attributes to allow for deletion of page attributes
page-retractions
(mapv #(vector :db/retract (:db/id e) %) (keys deleteable-page-attributes))]
(conj page-retractions (merge m' deleteable-page-attributes)))
[m'])]
(swap! txs-state into txs)))
(update-page-when-save-block txs-state block-entity m)
;; Remove orphaned refs from block
(when-not (config/db-based-graph? (state/get-current-repo))
(let [remove-self-page #(remove (fn [b]
(= (:db/id b) (:db/id (:block/page block-entity)))) %)
old-refs (remove-self-page (:block/refs block-entity))
new-refs (remove-self-page (:block/refs m))]
(remove-orphaned-page-refs! (:db/id block-entity) txs-state old-refs new-refs))))
(remove-orphaned-refs-when-save txs-state block-entity m))
(swap! txs-state conj (dissoc m :db/other-tx))
;; handle others txs
(let [other-tx (:db/other-tx m)]
(when (seq other-tx)
(swap! txs-state (fn [txs]
(vec (concat txs other-tx)))))
(swap! txs-state conj (dissoc m :db/other-tx)))
this))