diff --git a/deps.edn b/deps.edn index 38900323c1..b1658af9f1 100644 --- a/deps.edn +++ b/deps.edn @@ -17,9 +17,6 @@ metosin/komponentit #:mvn{:version "0.3.10"} instaparse/instaparse #:mvn{:version "1.4.10"} borkdude/sci #:mvn{:version "0.2.5"} - garden/garden #:mvn{:version "1.3.10"} - stylefy/stylefy #:mvn{:version "3.0.0"} - stylefy/reagent #:mvn{:version "3.0.0"} tick/tick #:mvn{:version "0.4.26-alpha"} cljc.java-time/cljc.java-time #:mvn{:version "0.1.9"} com.rpl/specter #:mvn{:version "1.1.3"} diff --git a/package.json b/package.json index 921e705b33..ad5a5c9138 100644 --- a/package.json +++ b/package.json @@ -107,8 +107,6 @@ "@js-joda/core": "1.12.0", "@js-joda/locale_en-us": "3.1.1", "@js-joda/timezone": "2.2.0", - "@material-ui/core": "^4.10.1", - "@material-ui/icons": "^4.9.1", "@sentry/integrations": "^6.17.3", "@sentry/react": "^6.17.3", "@sentry/tracing": "^6.17.3", diff --git a/resources/public/index.html b/resources/public/index.html index 3a4ef9fb8c..9fea1a6c4f 100644 --- a/resources/public/index.html +++ b/resources/public/index.html @@ -5,8 +5,6 @@ - - diff --git a/src/cljs/athens/components.cljs b/src/cljs/athens/components.cljs index 72bf351cb2..132de98808 100644 --- a/src/cljs/athens/components.cljs +++ b/src/cljs/athens/components.cljs @@ -1,7 +1,7 @@ (ns athens.components (:require - ["@chakra-ui/react" :refer [Checkbox Box Button]] - ["@material-ui/icons/Edit" :default Edit] + ["/components/Icons/Icons" :refer [PencilIcon]] + ["@chakra-ui/react" :refer [Checkbox Box IconButton Button]] [athens.db :as db] [athens.parse-renderer :refer [component]] [athens.reactive :as reactive] @@ -89,13 +89,7 @@ :position "relative" :sx {"> .block-container" {:ml 0 :pr "1.3rem" - "textarea" {:background "transparent"}} - "> svg" {:position "absolute" - :right "5px" - :top "5px" - :fontSize "1rem" - :zIndex "5" - :cursor "pointer"}}} + "textarea" {:background "transparent"}}}} (let [block (reactive/get-reactive-block-document [:block/uid block-uid])] [:<> [blocks/block-el @@ -103,10 +97,16 @@ {:linked-ref false} {:block-embed? true}] (when-not @(subscribe [:editing/is-editing uid]) - [:> Edit - {:on-click (fn [e] - (.. e stopPropagation) - (dispatch [:editing/uid uid]))}])])]) + [:> IconButton {:position "absolute" + :right 1 + :top 1 + :size "xs" + :fontSize "1rem" + :zIndex "5" + :on-click (fn [e] + (.. e stopPropagation) + (dispatch [:editing/uid uid]))} + [:> PencilIcon]])])]) ;; roam actually hides the brackets around [[embed]] [:span "{{" content "}}"]))) diff --git a/src/cljs/athens/electron/db_menu/status_indicator.cljs b/src/cljs/athens/electron/db_menu/status_indicator.cljs index 084a11b01c..c265a81c33 100644 --- a/src/cljs/athens/electron/db_menu/status_indicator.cljs +++ b/src/cljs/athens/electron/db_menu/status_indicator.cljs @@ -1,8 +1,7 @@ (ns athens.electron.db-menu.status-indicator (:require - ["@chakra-ui/react" :refer [Box Tooltip Spinner]] - ["@material-ui/icons/CheckCircle" :default CheckCircle] - ["@material-ui/icons/Error" :default Error])) + ["/components/Icons/Icons" :refer [CheckmarkCircleFillIcon ExclamationCircleFillIcon]] + ["@chakra-ui/react" :refer [Box Tooltip Spinner]])) (defn status-indicator @@ -27,10 +26,10 @@ (cond (= status :closed) [:> Tooltip {:label "Disconnected"} - [:> Error]] + [:> ExclamationCircleFillIcon]] (= status :running) [:> Tooltip {:label "Synced"} - [:> CheckCircle]] + [:> CheckmarkCircleFillIcon]] :else [:> Tooltip {:label "Synchronizing..."} [:> Spinner {:emptyColor "background.vibrancy" :speed "2s" :size "xs"}]])]) diff --git a/src/cljs/athens/style.cljs b/src/cljs/athens/style.cljs index a1bf274ee1..83d17f2cfc 100644 --- a/src/cljs/athens/style.cljs +++ b/src/cljs/athens/style.cljs @@ -2,9 +2,7 @@ (:require [athens.config :as config] [athens.util :as util] - [re-frame.core :refer [reg-sub subscribe]] - [stylefy.core :as stylefy] - [stylefy.reagent :as stylefy-reagent])) + [re-frame.core :refer [reg-sub subscribe]])) (reg-sub @@ -58,7 +56,6 @@ (defn init [] - (stylefy/init {:dom (stylefy-reagent/init)}) ;; hide re-frame-10x by default (when config/debug? (util/hide-10x))) diff --git a/src/cljs/athens/views/blocks/core.cljs b/src/cljs/athens/views/blocks/core.cljs index 4380ad61b1..664395a4d7 100644 --- a/src/cljs/athens/views/blocks/core.cljs +++ b/src/cljs/athens/views/blocks/core.cljs @@ -3,6 +3,7 @@ ["/components/Block/components/Anchor" :refer [Anchor]] ["/components/Block/components/Container" :refer [Container]] ["/components/Block/components/Toggle" :refer [Toggle]] + ["/components/Layout/Layout" :refer [ReferenceGroup ReferenceBlock]] ["@chakra-ui/react" :refer [VStack Button Breadcrumb BreadcrumbItem BreadcrumbLink HStack]] [athens.common.logging :as log] [athens.db :as db] @@ -21,79 +22,12 @@ [athens.views.blocks.content :as content] [athens.views.blocks.context-menu :refer [handle-copy-unformatted handle-copy-refs]] [athens.views.blocks.drop-area-indicator :as drop-area-indicator] - [athens.views.references :refer [reference-group reference-block]] [com.rpl.specter :as s] [goog.functions :as gfns] [re-frame.core :as rf] [reagent.core :as r])) -;; Styles -;; -;; Blocks use Em units in many places rather than Rem units because -;; blocks need to scale with their container: sidebar blocks are -;; smaller than main content blocks, for instance. - - -(def block-container-inner-style - {"&.show-tree-indicator:before" {:content "''" - :position "absolute" - :width "1px" - :left "calc(1.375em + 1px)" - :top "2em" - :bottom "0" - :opacity "0" - :transform "translateX(50%)" - :transition "background-color 0.2s ease-in-out, opacity 0.2s ease-in-out" - :background "separator.divider"} - "&:hover.show-tree-indicator:before, &:focus-within.show-tree-indicator:before" {:opacity 1} - "&:after" {:content "''" - :zIndex 0 - :position "absolute" - :inset "1px 0" - :opacity 0 - :pointerEvents "none" - :borderRadius "sm" - :transition "opacity 0.075s ease-in-out" - :background "link"} - "&.is-selected:after" {:opacity 0.2} - "&.is-presence .block-content" {:padding-right "1rem"} - ".user-avatar" {:position "absolute" - :left "4px" - :top "4px"} - ".block-body" {:display "grid" - :gridTemplateColumns "1em 1em 1fr auto" - :gridTemplateRows "0 1fr 0" - :gridTemplateAreas " - 'above above above above' - 'toggle bullet content refs' - 'below below below below'" - :borderRadius "0.5rem" - :position "relative"} - "&:hover > .block-toggle, &:focus-within > .block-toggle" {:opacity "1"} - "button.block-edit-toggle" {:position "absolute" - :appearance "none" - :width "100%" - :background "none" - :border 0 - :cursor "text" - :display "block" - :z-index 1 - :top 0 - :right 0 - :bottom 0 - :left 0} - ".block-embed" {:borderRadius "sm" - :sx {"--block-surface-color" "background.basement"} - :bg "background.basement" - ".block-container" {:marginLeft 0.5}} - ".block-content" {:gridArea "content" - :minHeight "1.5em"} - "&.is-linked-ref" {:bg "background-attic"} - ".block-container" {:marginLeft "2rem" - :gridArea "body"}}) - - ;; Inline refs ;; block-el depends on inline-linked-refs-el, which in turn depends on block-el @@ -125,13 +59,13 @@ (let [{:keys [block parents embed-id]} @state block (reactive/get-reactive-block-document (:db/id block))] [:<> - [:> HStack + [:> HStack {:lineHeight "1"} [:> Toggle {:isOpen (:open? @state) :on-click (fn [e] (.. e stopPropagation) (swap! state update :open? not))}] - [:> Breadcrumb {:fontSize "0.7em"} + [:> Breadcrumb {:fontSize "xs" :color "foreground.secondary"} (doall (for [{:keys [node/title block/string block/uid] :as breadcrumb-block} (if (or (:open? @state) (not (:focus? @state))) @@ -173,22 +107,20 @@ (when (not-empty refs) [:> VStack {:as "aside" :align "stretch" + :spacing 3 :key "Inline Linked References" :zIndex 2 - :mt 2 - :mb 4 - :ml 6 - :py 2 + :ml 4 :px 4 - :borderRadius "sm" + :borderRadius "md" :background "background.basement"} (doall (for [[group-title group] refs] - [reference-group {:title group-title - :key (str "group-" group-title)} + [:> ReferenceGroup {:title group-title + :key (str "group-" group-title)} (doall (for [block' group] - [reference-block {:key (str "ref-" (:block/uid block'))} + [:> ReferenceBlock {:key (str "ref-" (:block/uid block'))} [ref-comp block' state]]))]))]))) @@ -399,9 +331,7 @@ (when (not= string (:string/previous @state)) (swap! state assoc :string/previous string :string/local string)) - [:> Container {:sx (merge block-container-inner-style - {"--block-surface-color" "background.floor"}) - :isDragging (and dragging (not is-selected)) + [:> Container {:isDragging (and dragging (not is-selected)) :isSelected is-selected :hasChildren (seq children) :isOpen open diff --git a/src/cljs/athens/views/devtool.cljs b/src/cljs/athens/views/devtool.cljs index 41ee5291b3..4c7e7bb0c4 100644 --- a/src/cljs/athens/views/devtool.cljs +++ b/src/cljs/athens/views/devtool.cljs @@ -1,8 +1,7 @@ (ns athens.views.devtool (:require - ["@chakra-ui/react" :refer [Box Button Table Thead Tbody Th Tr Td Input ButtonGroup]] - ["@material-ui/icons/ChevronLeft" :default ChevronLeft] - ["@material-ui/icons/Clear" :default Clear] + ["/components/Icons/Icons" :refer [XmarkIcon ChevronLeftIcon]] + ["@chakra-ui/react" :refer [Box IconButton Button Table Thead Tbody Th Tr Td Input ButtonGroup]] [athens.config :as config] [athens.db :as db :refer [dsdb]] [cljs.pprint :as pp] @@ -231,7 +230,7 @@ (-> s (update :navs subvec 0 i) (dissoc :viewer))))} - [:<> [:> ChevronLeft] [:span (first nav)]]]))) + [:<> [:> ChevronLeftIcon] [:span (first nav)]]]))) [:h3 (pr-str (type navved-data))] [:div [:span "View as "] @@ -353,8 +352,8 @@ (defn devtool-close-el [] - [:> Button {:onClick #(dispatch [:devtool/toggle])} - [:> Clear]]) + [:> IconButton {:onClick #(dispatch [:devtool/toggle])} + [:> XmarkIcon]]) (defn devtool-el diff --git a/src/cljs/athens/views/pages/all_pages.cljs b/src/cljs/athens/views/pages/all_pages.cljs index 03aed2f98a..05de0ca749 100644 --- a/src/cljs/athens/views/pages/all_pages.cljs +++ b/src/cljs/athens/views/pages/all_pages.cljs @@ -7,7 +7,8 @@ [athens.db :as db] [athens.router :as router] [clojure.string :refer [lower-case]] - [re-frame.core :as rf])) + [re-frame.core :as rf] + [reagent.core :as r])) ;; Sort state and logic @@ -64,21 +65,28 @@ (defn- sortable-header ([column-id label width isNumeric] (let [sorted-by @(rf/subscribe [:all-pages/sorted-by]) - growing? @(rf/subscribe [:all-pages/sort-order-ascending?])] - [:> Th {:width width :isNumeric isNumeric} + growing? @(rf/subscribe [:all-pages/sort-order-ascending?]) + sort-icon (if growing? (r/as-element [:> ChevronUpIcon {:fontSize "0.5em"}]) + (r/as-element [:> ChevronDownIcon {:fontSize "0.5em"}]))] + [:> Th {:width width + :border 0 + :isNumeric isNumeric} [:> Button {:onClick #(rf/dispatch [:all-pages/sort-by column-id]) - :size "xs" + :size "sm" :textTransform "uppercase" + :display "flex" + :height "1em" + :overflow "hidden" :gap "0.25em" :variant "link" - :color "inherit" + :leftIcon (when (and isNumeric + (= column-id sorted-by)) + sort-icon) + :rightIcon (when (and (not isNumeric) + (= column-id sorted-by)) + sort-icon) :_hover {:textDecoration "none"}} - (when-not isNumeric label) - (when (= sorted-by column-id) - (if growing? - [:> ChevronUpIcon] - [:> ChevronDownIcon])) - (when isNumeric label)]]))) + label]]))) (defn page @@ -87,7 +95,8 @@ (fn [] (let [sorted-pages @(rf/subscribe [:all-pages/sorted all-pages])] [:> Box {:px 4 - :maxWidth "70rem" + :width "100%" + :maxWidth "75rem" :margin "calc(var(--app-header-height) + 2rem) auto 5rem"} [:> Table {:variant "striped"} [:> Thead diff --git a/src/cljs/athens/views/pages/daily_notes.cljs b/src/cljs/athens/views/pages/daily_notes.cljs index 87222c3373..6e7a6a93ef 100644 --- a/src/cljs/athens/views/pages/daily_notes.cljs +++ b/src/cljs/athens/views/pages/daily_notes.cljs @@ -33,7 +33,7 @@ :gap "1.5rem" :py "6rem" :px "2rem" - :alignItems "stretch" + :alignItems "center" :flex "1 1 100%" :flexDirection "column"} (doall diff --git a/src/cljs/athens/views/pages/graph.cljs b/src/cljs/athens/views/pages/graph.cljs index f76ff725ff..ef892959da 100644 --- a/src/cljs/athens/views/pages/graph.cljs +++ b/src/cljs/athens/views/pages/graph.cljs @@ -3,14 +3,10 @@ " Graph and controls are designed to work with local and global graph global graphs vs local graphs -- local graphs have an explicit root node - and customizations are based on that where as global doesn't have an explicit root - - Relies on material ui comps for user inputs."} + and customizations are based on that where as global doesn't have an explicit root"} athens.views.pages.graph (:require - ["@chakra-ui/react" :refer [Box Accordion AccordionButton AccordionItem AccordionPanel AccordionIcon]] - ["@material-ui/core/Slider" :as OldSlider] - ["@material-ui/core/Switch" :as OldSwitch] + ["@chakra-ui/react" :refer [Box Switch VStack FormControl FormLabel Input Accordion AccordionButton AccordionItem AccordionPanel]] ["react-force-graph-2d" :as ForceGraph2D] [athens.dates :as dates] [athens.db :as db] @@ -40,15 +36,6 @@ (def graph-ref-map (r/atom {})) -;; ------------------------------------------------------------------- -;; --- material ui --- - - -(def m-slider (r/adapt-react-class (.-default OldSlider))) - -(def m-switch (r/adapt-react-class (.-default OldSwitch))) - - ;; ------------------------------------------------------------------- ;; --- re-frame stuff --- ;; --- read comments at top of file for more --- @@ -169,117 +156,90 @@ ;; ------------------------------------------------------------------- ;; --- comps --- -(defn expansion-panel - [{:keys [heading controls]} local-node-eid] - (let [graph-conf @(subscribe [:graph/conf]) - graph-ref (get @graph-ref-map (or local-node-eid :global))] - [:> AccordionItem - [:> AccordionButton - [:> AccordionIcon] - heading] - [:> AccordionPanel - (doall - (for [{:keys [key comp label onChange no-simulation-reheat? props class]} controls] - ^{:key key} - [:div {:class class} label - [comp - (merge - props - {:value (key graph-conf) - :color "primary" - :onChange (fn [_ n-val] - (and onChange (onChange n-val)) - (rf/dispatch [:graph/set-conf key n-val]) - (when-not no-simulation-reheat? - (.d3ReheatSimulation graph-ref)))})]]))]])) - (defn graph-controls - "Uses a generic expansion panel(not super generic) - while this comp dictates all the controls and manipulations that can be made to the graph - Look at comment below for code theme - to get a sense of the structure" - ([] [graph-controls nil]) - ([local-node-eid] - (fn [] - (let [graph-conf @(subscribe [:graph/conf]) - graph-ref (get @graph-ref-map (or local-node-eid :global)) - - ;; code theme - ;; category -- for eg node-section and section related data - ;; controls -- for eg node-controls and their props - ;; props -- for eg orphans? inside a control are props for the editing-comp(for slider or toggle) - ;; other-keys describe more about the comp - node-controls [{:key :hlt-link-levels - :label "No. of link levels to highlight" - :props {:min 1 - :max 5 - :step 1 - :marks true} - :comp m-slider - :no-simulation-reheat? true} - {:key :orphans? - :label "Orphan nodes" - :comp m-switch - :props {:checked (:orphans? graph-conf)} - :class "switch" - :no-simulation-reheat? true} - {:key :daily-notes? - :label "Daily notes" - :comp m-switch - :props {:checked (:daily-notes? graph-conf)} - :class "switch" - :no-simulation-reheat? true}] - node-section {:heading "Nodes" - :controls node-controls} - - - force-controls [{:key :link-distance - :label "Link Distance" - :props {:min 5 - :max 95} - :comp m-slider - :class "slider" - :onChange (fn [val] (and graph-ref (.. graph-ref (d3Force "link") (distance val))))} - {:key :charge-strength - :label "Attraction force" - :props {:min -30 - :max 0} - :comp m-slider - :class "slider" - :onChange (fn [val] (and graph-ref (.. graph-ref (d3Force "charge") (strength val))))}] - force-section {:heading "Forces" - :controls force-controls} - - local-controls [{:key :local-depth - :label "Local Depth" - :props {:min 1 - :max 5 - :step 1 - :marks true} - :class "slider" - :comp m-slider - :no-simulation-reheat? true} - {:key :root-links-only? - :label "Only root links" - :comp m-switch - :class "switch" - :props {:checked (:root-links-only? graph-conf)} - :no-simulation-reheat? true}] - local-section {:heading "Local options" - :controls local-controls}] - [:> Accordion {:width "14em" - :position "fixed" - :allowMultiple true - :top "4rem" - :right 0} - (doall - (for [{:keys [heading] :as section} (remove nil? [(when-not local-node-eid - node-section) - force-section - (when local-node-eid - local-section)])] - ^{:key heading} - [expansion-panel section local-node-eid]))])))) + [local-node-eid] + (fn [] + (let [graph-conf @(subscribe [:graph/conf]) + graph-ref (get @graph-ref-map (or local-node-eid :global))] + [:> Accordion {:width "14em" + :defaultIndex 0 + :position "absolute" + :bg "background.basement" + :overflow "hidden" + :p 0 + :borderRadius "md" + :allowToggle true + :allowMultiple true + :bottom 2 + :right 2} + (when-not local-node-eid + [:> AccordionItem {:borderTop 0} + [:> AccordionButton {:borderRadius "sm"} + "Nodes"] + [:> AccordionPanel + [:> VStack {:align "stretch"} + [:> FormControl + [:> FormLabel "Highlighted link levels"] + [:> Input {:type "number" + :value (or (:hlt-link-levels graph-conf) 1) + :min 1 + :max 5 + :step 1 + :onChange (fn [e] (rf/dispatch [:graph/set-conf :hlt-link-levels (.. e -target -value)]))}]] + [:> Switch {:isChecked (:orphans? graph-conf) + :onChange (fn [e] + (rf/dispatch [:graph/set-conf :orphans? (.. e -target -checked)]) + (.d3ReheatSimulation graph-ref))} + "Orphan nodes"] + [:> Switch {:isChecked (:daily-notes? graph-conf) + :onChange (fn [e] + (rf/dispatch [:graph/set-conf :daily-notes? (.. e -target -checked)]) + (.d3ReheatSimulation graph-ref))} + "Daily notes"]]]]) + [:> AccordionItem + [:> AccordionButton {:borderRadius "sm"} + "Forces"] + [:> AccordionPanel + [:> VStack {:align "stretch"} + [:> FormControl + [:> FormLabel "Link distance"] + [:> Input {:type "number" + :value (:link-distance graph-conf) + :min 5 + :max 95 + :step 10 + :onChange (fn [e] + ((and graph-ref (.. graph-ref (d3Force "link") (distance (.. e -target -value))))) + (.d3ReheatSimulation graph-ref))}]] + [:> FormControl + [:> FormLabel "Attraction force"] + [:> Input {:type "number" + :value (:charge-strength graph-conf) + :min -30 + :max 0 + :step 5 + :onChange (fn [e] + ((and graph-ref (.. graph-ref (d3Force "charge") (distance (.. e -target -value))))) + (.d3ReheatSimulation graph-ref))}]]]]] + (when local-node-eid + [:> AccordionItem + [:> AccordionButton {:borderRadius "sm"} + "Local options"] + [:> AccordionPanel + [:> VStack {:align "stretch"} + [:> FormControl + [:> FormLabel "Local depth"] + [:> Input {:type "number" + :value (:local-depth graph-conf) + :min 1 + :max 5 + :step 1 + :onChange (fn [e] (rf/dispatch [:graph/set-conf :local-depth (.. e -target -value)]))}]] + [:> Switch {:isChecked (:root-links-only? graph-conf) + :onChange (fn [e] + (rf/dispatch [:graph/set-conf :root-links-only? (.. e -target -checked)]))} + "Only root links?"]]]])]))) (defn graph-root @@ -296,12 +256,13 @@ {:component-did-mount (fn [this] (let [dom-node (dom/dom-node this) + dom-root (if local-node-eid ".graph-page" "#app") graph-conf @(subscribe [:graph/conf]) graph-ref (get @graph-ref-map (or local-node-eid :global))] ;; set canvas dimensions - (swap! dimensions assoc :width (-> dom-node (.. (closest "#app")) + (swap! dimensions assoc :width (-> dom-node (.. (closest dom-root)) .-parentNode .-clientWidth)) - (swap! dimensions assoc :height (-> dom-node (.. (closest "#app")) + (swap! dimensions assoc :height (-> dom-node (.. (closest dom-root)) .-parentNode .-clientHeight)) ;; set init forces for graph (when graph-ref @@ -463,12 +424,22 @@ (let [local-node-eid (when block-uid (->> [:block/uid block-uid] (d/pull @db/dsdb '[:db/id]) :db/id))] - [:> Box {:class "graph-page" - :gridColumn "1 / -1" - :position "fixed" - :top 0 - :left 0 - :width "100vw" - :height "100vh"} - [graph-root local-node-eid] + [:<> + [:> Box (if local-node-eid + {:class "graph-page" + :alignSelf "stretch" + :justifySelf "stretch" + :overflow "hidden" + :height "20em" + :borderRadius "lg" + :bg "background.basement" + :position "relative"} + {:class "graph-page" + :gridColumn "1 / -1" + :position "fixed" + :top 0 + :left 0 + :width "100vw" + :height "100vh"}) + [graph-root local-node-eid]] [graph-controls local-node-eid]]))) diff --git a/src/cljs/athens/views/pages/node_page.cljs b/src/cljs/athens/views/pages/node_page.cljs index 0139d40cd1..d2a3b40deb 100644 --- a/src/cljs/athens/views/pages/node_page.cljs +++ b/src/cljs/athens/views/pages/node_page.cljs @@ -2,13 +2,10 @@ (:require ["/components/Block/components/Anchor" :refer [Anchor]] ["/components/Confirmation/Confirmation" :refer [Confirmation]] + ["/components/Icons/Icons" :refer [EllipsisHorizontalIcon GraphIcon BookmarkIcon BookmarkFillIcon TrashIcon]] + ["/components/Layout/Layout" :refer [PageReferences ReferenceBlock ReferenceGroup]] ["/components/Page/Page" :refer [PageHeader PageBody PageFooter TitleContainer]] - ["@chakra-ui/react" :refer [Text Box Button Portal IconButton AccordionIcon AccordionItem AccordionPanel MenuDivider MenuButton Menu MenuList MenuItem Accordion AccordionButton Breadcrumb BreadcrumbItem BreadcrumbLink VStack]] - ["@material-ui/icons/Bookmark" :default Bookmark] - ["@material-ui/icons/BookmarkBorder" :default BookmarkBorder] - ["@material-ui/icons/BubbleChart" :default BubbleChart] - ["@material-ui/icons/Delete" :default Delete] - ["@material-ui/icons/MoreHoriz" :default MoreHoriz] + ["@chakra-ui/react" :refer [Box Button Portal IconButton MenuDivider MenuButton Menu MenuList MenuItem Breadcrumb BreadcrumbItem BreadcrumbLink VStack]] [athens.common-db :as common-db] [athens.common.sentry :refer-macros [wrap-span-no-new-tx]] [athens.common.utils :as utils] @@ -21,7 +18,6 @@ [athens.views.blocks.core :as blocks] [athens.views.blocks.textarea-keydown :as textarea-keydown] [athens.views.hoc.perf-mon :as perf-mon] - [athens.views.references :refer [reference-group reference-block]] [clojure.string :as str] [datascript.core :as d] [komponentit.autosize :as autosize] @@ -217,30 +213,31 @@ "aria-label" "Page menu" :gridArea "menu" :justifySelf "flex-end" + :size "md" :alignSelf "center" :bg "transparent" - :height "2.25em" :width "2.25em" :mr "0.5em" :borderRadius "full" :sx {"span" {:display "contents"} "button svg:first-of-type" {:marginRight "0.25rem"}}} - [:> MoreHoriz]] + [:> EllipsisHorizontalIcon]] [:> Portal [:> MenuList {:sx {"button svg:first-of-type" {:marginRight "0.25rem"}}} [:<> (if sidebar - [:> MenuItem {:onClick #(dispatch [:left-sidebar/remove-shortcut title])} - [:> BookmarkBorder] + [:> MenuItem {:onClick #(dispatch [:left-sidebar/remove-shortcut title]) + :icon (r/as-element [:> BookmarkFillIcon])} "Remove Shortcut"] - [:> MenuItem {:onClick #(dispatch [:left-sidebar/add-shortcut title])} - [:> Bookmark] + [:> MenuItem {:onClick #(dispatch [:left-sidebar/add-shortcut title]) + :icon (r/as-element [:> BookmarkIcon])} [:span "Add Shortcut"]]) - [:> MenuItem {:onClick #(dispatch [:right-sidebar/open-item uid true])} - [:> BubbleChart] + [:> MenuItem {:onClick #(dispatch [:right-sidebar/open-item uid true]) + :icon (r/as-element [:> GraphIcon])} "Show Local Graph"]] [:> MenuDivider] - [:> MenuItem {:onClick (fn [] + [:> MenuItem {:icon (r/as-element [:> TrashIcon]) + :onClick (fn [] ;; if page being deleted is in right sidebar, remove from right sidebar (when (contains? @(subscribe [:right-sidebar/items]) uid) (dispatch [:right-sidebar/close-item uid])) @@ -255,7 +252,7 @@ (if daily-note? (dispatch [:daily-note/delete uid title]) (dispatch [:page/delete title])))} - [:> Delete] "Delete Page"]]]])) + "Delete Page"]]]])) (defn ref-comp @@ -270,8 +267,8 @@ (fn [_] (let [{:keys [block parents embed-id]} @state block (reactive/get-reactive-block-document (:db/id block))] - [:<> - [:> Breadcrumb {:fontSize "0.7em" :pl 6 :opacity 0.75} + [:> VStack {:spacing 0 :align "stretch"} + [:> Breadcrumb {:fontSize "sm" :pl 4 :variant "strict" :color "foreground.secondary"} (doall (for [{:keys [node/title block/string block/uid]} parents] [:> BreadcrumbItem {:key (str "breadcrumb-" uid)} @@ -288,119 +285,94 @@ (defn linked-ref-el - [state daily-notes? title] + [state title] (let [linked? "Linked References" linked-refs (wrap-span-no-new-tx "get-reactive-linked-references" (reactive/get-reactive-linked-references [:node/title title]))] - (when (or (and daily-notes? (not-empty linked-refs)) - (not daily-notes?)) - [:> Accordion {:index (if (get @state linked?) 0 nil)} - [:> AccordionItem - [:h2 - [:> AccordionButton {:onClick (fn [] (swap! state update linked? not))} - [:> AccordionIcon] - linked? - [:> Text {:ml "auto" - :fontWeight "medium" - :color "foreground.secondary" - :borderRadius "full"} - (count linked-refs)]]] - [:> AccordionPanel {:p 0} - [:> VStack {:spacing 6 - :pl 9 - :align "stretch"} - (doall - (for [[group-title group] linked-refs] - [reference-group {:key (str "group-" group-title) - :title group-title - :on-click-title (fn [e] - (let [shift? (.-shiftKey e) - parsed-title (parse-renderer/parse-title group-title)] - (rf/dispatch [:reporting/navigation {:source :main-page-linked-refs ; NOTE: this might be also used in right-pane situation - :target :page - :pane (if shift? - :right-pane - :main-pane)}]) - (router/navigate-page parsed-title e)))} - (doall - (for [block group] - [reference-block {:key (str "ref-" (:block/uid block))} - [ref-comp block]]))]))]]]]))) + (when (not-empty linked-refs) + [:> PageReferences {:count (count linked-refs) + :title "Linked References" + :onOpen (fn [] (swap! state update linked? not)) + :onClose (fn [] (swap! state update linked? not)) + :defaultIsOpen (get @state linked?)} + (doall + (for [[group-title group] linked-refs] + [:> ReferenceGroup {:key (str "group-" group-title) + :title group-title + :onClickTitle (fn [e] + (let [shift? (.-shiftKey e) + parsed-title (parse-renderer/parse-title group-title)] + (rf/dispatch [:reporting/navigation {:source :main-page-linked-refs ; NOTE: this might be also used in right-pane situation + :target :page + :pane (if shift? + :right-pane + :main-pane)}]) + (router/navigate-page parsed-title e)))} + (doall + (for [block group] + [:> ReferenceBlock {:key (str "ref-" (:block/uid block))} + [ref-comp block]]))]))]))) (defn unlinked-ref-el - [state daily-notes? unlinked-refs title] - (let [unlinked? "Unlinked References"] - (when (not daily-notes?) - [:> Accordion {:index (if (get @state unlinked?) 0 nil)} - [:> AccordionItem {:isDisabled (empty @unlinked-refs)} - [:> Box {:as "h2" :position "relative"} - [:> AccordionButton {:onClick (fn [] - (if (get @state unlinked?) - (swap! state assoc unlinked? false) - (let [un-refs (get-unlinked-references (escape-str title))] - (swap! state assoc unlinked? true) - (reset! unlinked-refs un-refs))))} - [:> AccordionIcon] - unlinked? - [:> Text {:ml "auto" - :fontWeight "medium" - :color "foreground.secondary" - :borderRadius "full"} - (count @unlinked-refs)]] - (when (and unlinked? (not-empty @unlinked-refs)) - [:> Button {:position "absolute" - :size "xs" - :top 1 - :right 1 - :onClick (fn [] - (let [unlinked-str-ids (->> @unlinked-refs - (mapcat second) - (map #(select-keys % [:block/string :block/uid])))] ; to remove the unnecessary data before dispatching the event - (dispatch [:unlinked-references/link-all unlinked-str-ids title])) - - (swap! state assoc unlinked? false) - - (reset! unlinked-refs []))} - "Link All"])] - [:> AccordionPanel {:p 0} - [:> VStack {:spacing 6 - :pl 1 - :align "stretch"} + [state unlinked-refs title] + (let [unlinked? "Unlinked References" + link-all-unlinked (fn [] + (let [unlinked-str-ids + (->> @unlinked-refs + (mapcat second) + (map #(select-keys % [:block/string :block/uid])))] ; to remove the unnecessary data before dispatching the event + (dispatch [:unlinked-references/link-all unlinked-str-ids title])) + (swap! state assoc unlinked? false) + (reset! unlinked-refs []))] + [:> PageReferences {:defaultIsOpen false + :count (count @unlinked-refs) + :showIfEmpty true + :refs @unlinked-refs + :title "Unlinked References" + :extras (r/as-element [:> Button {:variant "link" + :size "sm" + :flexShrink 0 + :onClick link-all-unlinked} + "Link all"]) + :onOpen #(let [un-refs (get-unlinked-references (escape-str title))] + (swap! state assoc unlinked? true) + (reset! unlinked-refs un-refs)) + :onClose #(swap! state assoc unlinked? false)} + (doall + (for [[[group-title] group] @unlinked-refs] + [:> ReferenceGroup + {:title group-title + :onClickTitle (fn [e] + (let [shift? (.-shiftKey e) + parsed-title (parse-renderer/parse-title group-title)] + (rf/dispatch [:reporting/navigation {:source :main-unlinked-refs ; NOTE: this isn't always `:main-unlinked-refs` it can also be `:right-pane-unlinked-refs` + :target :page + :pane (if shift? + :right-pane + :main-pane)}]) + (router/navigate-page parsed-title e)))} (doall - (for [[[group-title] group] @unlinked-refs] - [reference-group - {:title group-title - :on-click-title (fn [e] - (let [shift? (.-shiftKey e) - parsed-title (parse-renderer/parse-title group-title)] - (rf/dispatch [:reporting/navigation {:source :main-unlinked-refs ; NOTE: this isn't always `:main-unlinked-refs` it can also be `:right-pane-unlinked-refs` - :target :page - :pane (if shift? - :right-pane - :main-pane)}]) - (router/navigate-page parsed-title e)))} - (doall - (for [block group] - [reference-block - {:key (str "ref-" (:block/uid block)) - :actions (when unlinked? - [:> Button {:marginTop "1.5em" - :size "xs" - :flex "0 0" - :float "right" - :variant "link" - :onClick (fn [] - (let [hm (into (hash-map) @unlinked-refs) - new-unlinked-refs (->> (update-in hm [group-title] #(filter (fn [{:keys [block/uid]}] - (= uid (:block/uid block))) - %)) - seq)] - ;; ctrl-z doesn't work though, because Unlinked Refs aren't reactive to datascript. - (reset! unlinked-refs new-unlinked-refs) - (dispatch [:unlinked-references/link block title])))} - "Link"])} - [ref-comp block]]))]))]]]]))) + (for [block group] + [:> ReferenceBlock + {:key (str "ref-" (:block/uid block)) + :actions (when unlinked? + (r/as-element [:> Button {:marginTop "1.5em" + :size "xs" + :flex "0 0" + :float "right" + :variant "link" + :onClick (fn [] + (let [hm (into (hash-map) @unlinked-refs) + new-unlinked-refs (->> (update-in hm [group-title] #(filter (fn [{:keys [block/uid]}] + (= uid (:block/uid block))) + %)) + seq)] + ;; ctrl-z doesn't work though, because Unlinked Refs aren't reactive to datascript. + (reset! unlinked-refs new-unlinked-refs) + (dispatch [:unlinked-references/link block title])))} + "Link"]))} + [ref-comp block]]))]))])) ;; TODO: where to put page-level link filters? @@ -475,9 +447,10 @@ ;; References [:> PageFooter [perf-mon/hoc-perfmon-no-new-tx {:span-name "linked-ref-el"} - [linked-ref-el state on-daily-notes? title]] - [perf-mon/hoc-perfmon-no-new-tx {:span-name "unlinked-ref-el"} - [unlinked-ref-el state on-daily-notes? unlinked-refs title]]]])))) + [linked-ref-el state title]] + (when-not on-daily-notes? + [perf-mon/hoc-perfmon-no-new-tx {:span-name "unlinked-ref-el"} + [unlinked-ref-el state unlinked-refs title]])]])))) (defn page diff --git a/src/cljs/athens/views/references.cljs b/src/cljs/athens/views/references.cljs index 8dc8bc756e..5a773a9f18 100644 --- a/src/cljs/athens/views/references.cljs +++ b/src/cljs/athens/views/references.cljs @@ -29,9 +29,9 @@ (defn reference-group ([props children] (let [{:keys [on-click-title title]} props] - [:> VStack {:spacing 2 :align "stretch"} - [reference-header {:on-click on-click-title - :title title}] + [:> VStack {:spacing 0 :align "stretch"} + (when title [reference-header {:on-click on-click-title + :title title}]) children]))) diff --git a/src/js/components/AppToolbar/AppToolbar.tsx b/src/js/components/AppToolbar/AppToolbar.tsx index 7541aa6fa9..89f215c6fa 100644 --- a/src/js/components/AppToolbar/AppToolbar.tsx +++ b/src/js/components/AppToolbar/AppToolbar.tsx @@ -10,14 +10,11 @@ import { AllPagesIcon, SettingsIcon, ContrastIcon, - DailyNotesIcon + DailyNotesIcon, + GraphIcon, + EllipsisHorizontalIcon } from '@/Icons/Icons'; -import { - BubbleChart, - MoreHoriz, -} from '@material-ui/icons'; - import { HTMLChakraProps, Portal, @@ -228,7 +225,7 @@ const SecondaryToolbarItems = (items) => { const SecondaryToolbarOverflowMenu = (items) => { return