diff --git a/src/main/frontend/components/sidebar.cljs b/src/main/frontend/components/sidebar.cljs index 5a3490fdcc..a40a82ec32 100644 --- a/src/main/frontend/components/sidebar.cljs +++ b/src/main/frontend/components/sidebar.cljs @@ -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) diff --git a/src/main/frontend/components/whiteboard.cljs b/src/main/frontend/components/whiteboard.cljs index 2f6f6df19b..5101c01736 100644 --- a/src/main/frontend/components/whiteboard.cljs +++ b/src/main/frontend/components/whiteboard.cljs @@ -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] diff --git a/src/main/frontend/components/whiteboard.css b/src/main/frontend/components/whiteboard.css index 7561292319..949acd31d4 100644 --- a/src/main/frontend/components/whiteboard.css +++ b/src/main/frontend/components/whiteboard.css @@ -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; +} diff --git a/src/main/frontend/db/model.cljs b/src/main/frontend/db/model.cljs index ae407b6ca4..4d2e7d4447 100644 --- a/src/main/frontend/db/model.cljs +++ b/src/main/frontend/db/model.cljs @@ -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))))