mirror of
https://github.com/logseq/logseq.git
synced 2026-06-01 19:01:22 +00:00
fix: enhance dashboard page
This commit is contained in:
@@ -560,7 +560,7 @@
|
||||
wide-mode? (state/sub :ui/wide-mode?)
|
||||
right-sidebar-blocks (state/sub-right-sidebar-blocks)
|
||||
route-name (get-in route-match [:data :name])
|
||||
margin-less-pages? (boolean (#{:graph :whiteboard :whiteboards} route-name))
|
||||
margin-less-pages? (boolean (#{:graph :whiteboard} route-name))
|
||||
db-restoring? (state/sub :db/restoring?)
|
||||
indexeddb-support? (state/sub :indexeddb/support?)
|
||||
page? (= :page route-name)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
(ns frontend.components.whiteboard
|
||||
(:require [datascript.core :as d]
|
||||
(:require [cljs.math :as math]
|
||||
[datascript.core :as d]
|
||||
[frontend.components.page :as page]
|
||||
[frontend.components.reference :as reference]
|
||||
[frontend.db.model :as model]
|
||||
@@ -25,6 +26,7 @@
|
||||
(when draw-component
|
||||
(draw-component name shape-id))))
|
||||
|
||||
;; TODO: make it reactive to db changes
|
||||
(rum/defc tldraw-preview < rum/reactive
|
||||
{:init (fn [state]
|
||||
(p/let [_ (loader/load :tldraw)]
|
||||
@@ -38,19 +40,59 @@
|
||||
(when generate-preview
|
||||
(generate-preview tldr))))
|
||||
|
||||
(rum/defc dashboard-card
|
||||
(rum/defc page-refs-count < rum/static
|
||||
[page-name]
|
||||
[:div.rounded.text-lg.cursor-pointer.flex.flex-col.gap-1.overflow-hidden.dashboard-card
|
||||
(let [page-entity (model/get-page page-name)
|
||||
refs-count (count (:block/_refs page-entity))]
|
||||
[:a.open-page-ref-link refs-count]))
|
||||
|
||||
(defn- get-page-display-name
|
||||
[page-name]
|
||||
(let [page-entity (model/get-page page-name)]
|
||||
(or (get-in page-entity [:block/properties :title] nil)
|
||||
(:block/original-name page-entity)
|
||||
page-name)))
|
||||
|
||||
;; This is not accurate yet
|
||||
;; (defn- get-page-human-update-time
|
||||
;; [page-name]
|
||||
;; (let [page-entity (model/get-page page-name)
|
||||
;; updated-at (:block/updated-at page-entity)]
|
||||
;; (str "Edited at " (util/time-ago (js/Date. updated-at)))))
|
||||
|
||||
(rum/defc dashboard-preview-card
|
||||
[page-name]
|
||||
[:div.dashboard-card.dashboard-preview-card.cursor-pointer.hover:shadow-lg
|
||||
{:on-mouse-down
|
||||
(fn [e]
|
||||
(util/stop e)
|
||||
(route-handler/redirect-to-whiteboard! page-name))}
|
||||
[:div.truncate.px-4.py-1.dashboard-card-title page-name]
|
||||
[:div.dashboard-card-title
|
||||
[:div.flex.w-full
|
||||
[:div.dashboard-card-title-name (get-page-display-name page-name)]
|
||||
[:div.flex-1]
|
||||
(page-refs-count page-name)]
|
||||
;; [:div.flex.w-full
|
||||
;; [:div (get-page-human-update-time page-name)]
|
||||
;; [:div.flex-1]
|
||||
;; (page-refs-count page-name)]
|
||||
]
|
||||
[:div.p-4.h-64.flex.justify-center
|
||||
(tldraw-preview page-name)]])
|
||||
|
||||
(rum/defc dashboard-create-card
|
||||
[]
|
||||
[:div.dashboard-card.dashboard-create-card.cursor-pointer
|
||||
{:on-mouse-down
|
||||
(fn [e]
|
||||
(util/stop e)
|
||||
(route-handler/redirect-to-whiteboard! (d/squuid)))}
|
||||
(ui/icon "plus")
|
||||
[:span.dashboard-create-card-caption
|
||||
"New whiteboard"]])
|
||||
|
||||
;; TODO: move it to util?
|
||||
(defn- use-component-rect
|
||||
(defn- use-component-size
|
||||
[ref]
|
||||
(let [[rect set-rect] (rum/use-state nil)]
|
||||
(rum/use-effect!
|
||||
@@ -67,25 +109,32 @@
|
||||
|
||||
(rum/defc whiteboard-dashboard
|
||||
[]
|
||||
(let [whiteboard-names (model/get-all-whiteboard-names (state/get-current-repo))
|
||||
(let [whiteboards (model/get-all-whiteboards (state/get-current-repo))
|
||||
whiteboard-names (map :block/name whiteboards)
|
||||
ref (rum/use-ref nil)
|
||||
rect (use-component-rect ref)
|
||||
container-width (when rect (.-width rect))
|
||||
rect (use-component-size ref)
|
||||
[container-width] (when rect [(.-width rect) (.-height rect)])
|
||||
cols (cond (< container-width 600) 1
|
||||
(< container-width 900) 2
|
||||
(< container-width 1200) 3
|
||||
:else 4)]
|
||||
[:div.p-4
|
||||
{:ref ref}
|
||||
(ui/button "Create new whiteboard"
|
||||
:small? true
|
||||
:on-click (fn [e]
|
||||
(util/stop e)
|
||||
(route-handler/redirect-to-whiteboard! (d/squuid))))
|
||||
[:div.gap-8.py-4.grid.grid-rows-auto
|
||||
{:style {:grid-template-columns (str "repeat(" cols ", minmax(0, 1fr))")}}
|
||||
(for [whiteboard-name whiteboard-names]
|
||||
[:<> {:key whiteboard-name} (dashboard-card whiteboard-name)])]]))
|
||||
:else 4)
|
||||
total-whiteboards (count whiteboards)
|
||||
empty-cards (- (max (* (math/ceil (/ (inc total-whiteboards) cols)) cols) (* 2 cols))
|
||||
(inc total-whiteboards))]
|
||||
[:<>
|
||||
[:h1.title
|
||||
"All whiteboards"
|
||||
[:span.opacity-50
|
||||
(str " · " total-whiteboards)]]
|
||||
[:div
|
||||
{:ref ref}
|
||||
[:div.gap-8.grid.grid-rows-auto
|
||||
{:style {:grid-template-columns (str "repeat(" cols ", minmax(0, 1fr))")}}
|
||||
(dashboard-create-card)
|
||||
(for [whiteboard-name whiteboard-names]
|
||||
[:<> {:key whiteboard-name} (dashboard-preview-card whiteboard-name)])
|
||||
(for [n (range empty-cards)]
|
||||
[:div.dashboard-card.dashboard-bg-card {:key n}])]]]))
|
||||
|
||||
(rum/defc whiteboard-references
|
||||
[name]
|
||||
|
||||
@@ -1,12 +1,65 @@
|
||||
.whiteboard-dashboard-bg-grid {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.dashboard-bg-card {
|
||||
background-color: var(--ls-secondary-background-color);
|
||||
border: 1px solid var(--ls-border-color);
|
||||
opacity: 0.3;
|
||||
}
|
||||
|
||||
.dashboard-card {
|
||||
@apply hover:shadow-lg;
|
||||
@apply rounded flex flex-col gap-1 overflow-hidden font-medium;
|
||||
height: 300px;
|
||||
}
|
||||
|
||||
.dashboard-preview-card {
|
||||
border: 1px solid var(--ls-border-color);
|
||||
}
|
||||
|
||||
.dashboard-create-card {
|
||||
@apply items-center justify-center relative;
|
||||
background-color: var(--ls-secondary-background-color);
|
||||
box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.06);
|
||||
border: 1px solid transparent;
|
||||
}
|
||||
|
||||
.dashboard-create-card i {
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.dashboard-create-card-caption {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
bottom: 12px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.dashboard-create-card:hover {
|
||||
background-color: var(--ls-selection-background-color);
|
||||
box-shadow: 0 4px 8px -2px rgba(16, 24, 40, 0.1),
|
||||
0 2px 4px -2px rgba(16, 24, 40, 0.06);
|
||||
border: 1px solid var(--ls-page-blockquote-border-color);
|
||||
}
|
||||
|
||||
.dashboard-card-title {
|
||||
color: var(--ls-primary-text-color);
|
||||
@apply px-4 py-1 flex flex-col;
|
||||
gap: 4px;
|
||||
border-bottom: 1px solid var(--ls-border-color);
|
||||
background-color: var(--ls-secondary-background-color);
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.dashboard-card-title-name {
|
||||
@apply truncate;
|
||||
color: var(--ls-primary-text-color);
|
||||
}
|
||||
|
||||
.single-block > :is(.block-content-wrapper, .editor-wrapper) {
|
||||
@@ -19,3 +72,15 @@
|
||||
.tl-logseq-cp-container > .page {
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
/**
|
||||
* ???
|
||||
*/
|
||||
.open-page-ref-link {
|
||||
@apply text-sm ml-2 px-1 flex items-center rounded;
|
||||
flex-shrink: 0;
|
||||
background-color: var(--ls-quaternary-background-color);
|
||||
font-size: 14px;
|
||||
color: var(--ls-primary-text-color);
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
@@ -63,9 +63,9 @@
|
||||
(when-let [repo (state/get-current-repo)]
|
||||
(->
|
||||
(react/q repo [:frontend.db.react/block id]
|
||||
{:query-fn (fn [_]
|
||||
(db-utils/pull (butlast block-attrs) id))}
|
||||
nil)
|
||||
{:query-fn (fn [_]
|
||||
(db-utils/pull (butlast block-attrs) id))}
|
||||
nil)
|
||||
react)))
|
||||
|
||||
(defn get-original-name
|
||||
@@ -861,14 +861,14 @@
|
||||
(when-let [db (conn/get-db repo)]
|
||||
(let [eid (:db/id (db-utils/entity repo [:block/uuid block-uuid]))]
|
||||
(->> (d/q
|
||||
'[:find ?id
|
||||
:in $ ?p %
|
||||
:where
|
||||
(child ?p ?c)
|
||||
[?c :block/uuid ?id]]
|
||||
db
|
||||
eid
|
||||
rules)
|
||||
'[:find ?id
|
||||
:in $ ?p %
|
||||
:where
|
||||
(child ?p ?c)
|
||||
[?c :block/uuid ?id]]
|
||||
db
|
||||
eid
|
||||
rules)
|
||||
(apply concat)))))
|
||||
|
||||
(defn get-block-immediate-children
|
||||
@@ -1179,14 +1179,14 @@
|
||||
aliases (set/difference pages #{page-id})]
|
||||
(->>
|
||||
(react/q repo
|
||||
[:frontend.db.react/page<-blocks-or-block<-blocks page-id]
|
||||
{}
|
||||
'[:find [(pull ?block ?block-attrs) ...]
|
||||
:in $ [?ref-page ...] ?block-attrs
|
||||
:where
|
||||
[?block :block/path-refs ?ref-page]]
|
||||
pages
|
||||
(butlast block-attrs))
|
||||
[:frontend.db.react/page<-blocks-or-block<-blocks page-id]
|
||||
{}
|
||||
'[:find [(pull ?block ?block-attrs) ...]
|
||||
:in $ [?ref-page ...] ?block-attrs
|
||||
:where
|
||||
[?block :block/path-refs ?ref-page]]
|
||||
pages
|
||||
(butlast block-attrs))
|
||||
react
|
||||
(remove (fn [block] (= page-id (:db/id (:block/page block)))))
|
||||
db-utils/group-by-page
|
||||
@@ -1209,17 +1209,17 @@
|
||||
aliases (set/difference pages #{page-id})]
|
||||
(->>
|
||||
(react/q repo
|
||||
[:frontend.db.react/page<-blocks-or-block<-blocks page-id]
|
||||
{:use-cache? false
|
||||
:query-fn (fn []
|
||||
(let [entities (mapcat (fn [id]
|
||||
(:block/_path-refs (db-utils/entity id))) pages)
|
||||
blocks (map (fn [e] {:block/parent (:block/parent e)
|
||||
:block/left (:block/left e)
|
||||
:block/page (:block/page e)}) entities)]
|
||||
{:entities entities
|
||||
:blocks blocks}))}
|
||||
nil)
|
||||
[:frontend.db.react/page<-blocks-or-block<-blocks page-id]
|
||||
{:use-cache? false
|
||||
:query-fn (fn []
|
||||
(let [entities (mapcat (fn [id]
|
||||
(:block/_path-refs (db-utils/entity id))) pages)
|
||||
blocks (map (fn [e] {:block/parent (:block/parent e)
|
||||
:block/left (:block/left e)
|
||||
:block/page (:block/page e)}) entities)]
|
||||
{:entities entities
|
||||
:blocks blocks}))}
|
||||
nil)
|
||||
react
|
||||
:entities
|
||||
(remove (fn [block] (= page-id (:db/id (:block/page block)))))
|
||||
@@ -1240,15 +1240,15 @@
|
||||
result (if page?
|
||||
(let [pages (page-alias-set repo (:block/name block))]
|
||||
(d/q
|
||||
'[:find [?block ...]
|
||||
:in $ [?ref-page ...] ?id
|
||||
:where
|
||||
[?block :block/refs ?ref-page]
|
||||
[?block :block/page ?p]
|
||||
[(not= ?p ?id)]]
|
||||
(conn/get-db repo)
|
||||
pages
|
||||
id))
|
||||
'[:find [?block ...]
|
||||
:in $ [?ref-page ...] ?id
|
||||
:where
|
||||
[?block :block/refs ?ref-page]
|
||||
[?block :block/page ?p]
|
||||
[(not= ?p ?id)]]
|
||||
(conn/get-db repo)
|
||||
pages
|
||||
id))
|
||||
(:block/_refs block))]
|
||||
(count result))))
|
||||
|
||||
@@ -1679,15 +1679,15 @@
|
||||
(defn get-macro-blocks
|
||||
[repo macro-name]
|
||||
(d/q
|
||||
'[:find [(pull ?b [*]) ...]
|
||||
:in $ ?macro-name
|
||||
:where
|
||||
[?b :block/type "macro"]
|
||||
[?b :block/properties ?properties]
|
||||
[(get ?properties :logseq.macro-name) ?name]
|
||||
[(= ?name ?macro-name)]]
|
||||
(conn/get-db repo)
|
||||
macro-name))
|
||||
'[:find [(pull ?b [*]) ...]
|
||||
:in $ ?macro-name
|
||||
:where
|
||||
[?b :block/type "macro"]
|
||||
[?b :block/properties ?properties]
|
||||
[(get ?properties :logseq.macro-name) ?name]
|
||||
[(= ?name ?macro-name)]]
|
||||
(conn/get-db repo)
|
||||
macro-name))
|
||||
|
||||
(defn whiteboard-page?
|
||||
[page-name]
|
||||
@@ -1713,12 +1713,13 @@
|
||||
;; (whiteboard-clj->tldr page blocks))) result)]
|
||||
;; tldrs))
|
||||
|
||||
(defn get-all-whiteboard-names
|
||||
(defn get-all-whiteboards
|
||||
[repo]
|
||||
(->> (d/q
|
||||
'[:find [(pull ?page [:block/name]) ...]
|
||||
'[:find [(pull ?page [:block/name
|
||||
:block/created-at
|
||||
:block/updated-at]) ...]
|
||||
:where
|
||||
[?page :block/name]
|
||||
[?page :block/whiteboard? true]]
|
||||
(conn/get-db repo))
|
||||
(map :block/name)))
|
||||
(conn/get-db repo))))
|
||||
|
||||
Reference in New Issue
Block a user