| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195 | (ns frontend.components.reference  (:require [clojure.string :as string]            [frontend.components.block :as block]            [frontend.components.content :as content]            [frontend.components.editor :as editor]            [frontend.components.svg :as svg]            [frontend.date :as date]            [frontend.db :as db]            [frontend.db-mixins :as db-mixins]            [frontend.handler.block :as block-handler]            [frontend.handler.page :as page-handler]            [frontend.state :as state]            [frontend.ui :as ui]            [frontend.util :as util]            [medley.core :as medley]            [rum.core :as rum]))(rum/defc filter-dialog-inner < rum/reactive  [filters-atom close-fn references page-name]  [:div.filters   [:div.sm:flex.sm:items-start    [:div.mx-auto.flex-shrink-0.flex.items-center.justify-center.h-12.w-12.rounded-full.bg-gray-200.text-gray-500.sm:mx-0.sm:h-10.sm:w-10     (svg/filter-icon)]    [:div.mt-3.text-center.sm:mt-0.sm:ml-4.sm:text-left     [:h3#modal-headline.text-lg.leading-6.font-medium "Filter"]     [:span.text-xs      "Click to include and shift-click to exclude. Click again to remove."]]]   (when (seq references)     (let [filters (rum/react filters-atom)]       [:div.mt-5.sm:mt-4.sm:flex.sm.gap-1.flex-wrap       (for [reference references]         (let [lc-reference (string/lower-case reference)               filtered (get filters lc-reference)               color (condp = filtered                       true "text-green-400"                       false "text-red-400"                       nil)]           [:button.border.rounded.px-1.mb-1.mr-1 {:key reference :class color :style {:border-color "currentColor"}                                                   :on-click (fn [e]                                                               (swap! filters-atom #(if (nil? (get filters lc-reference))                                                                                      (assoc % lc-reference (not (.-shiftKey e)))                                                                                      (dissoc % lc-reference)))                                                               (page-handler/save-filter! page-name @filters-atom))}            reference]))]))])(defn filter-dialog  [filters-atom references page-name]  (fn [close-fn]    (filter-dialog-inner filters-atom close-fn references page-name)))(defn- block-with-ref-level  [block level]  (if (:block/children block)    (-> (update block :block/children             (fn [blocks]               (map (fn [block]                      (let [level (inc level)                            block (assoc block :ref/level level)]                        (block-with-ref-level block level))) blocks)))        (assoc :ref/level level))    (assoc block :ref/level level)))(defn- blocks-with-ref-level  [page-blocks]  (map (fn [[page blocks]]         [page (map #(block-with-ref-level % 1) blocks)])    page-blocks))(rum/defcs references < rum/reactive  {:init (fn [state]           (let [page-name (first (:rum/args state))                 filters (when page-name                           (atom (page-handler/get-filters (string/lower-case page-name))))]             (assoc state ::filters filters)))}  [state page-name marker? priority?]  (when page-name    (let [filters-atom (get state ::filters)          block? (util/uuid-string? page-name)          block-id (and block? (uuid page-name))          page-name (string/lower-case page-name)          journal? (date/valid-journal-title? (string/capitalize page-name))          repo (state/get-current-repo)          ref-blocks (cond                       block-id                       (db/get-block-referenced-blocks block-id)                       :else                       (db/get-page-referenced-blocks page-name))          ref-pages (map (comp :block/original-name first) ref-blocks)          scheduled-or-deadlines (if (and journal?                                          (not (true? (state/scheduled-deadlines-disabled?)))                                          (= page-name (string/lower-case (date/journal-name))))                                   (db/get-date-scheduled-or-deadlines (string/capitalize page-name))                                   nil)          references (db/get-page-linked-refs-refed-pages repo page-name)          references (->> (concat ref-pages references)                          (remove nil?)                          (distinct))          filter-state (rum/react filters-atom)          filters (when (seq filter-state)                    (->> (group-by second filter-state)                         (medley/map-vals #(map first %))))          filtered-ref-blocks (->> (block-handler/filter-blocks repo ref-blocks filters true)                                   blocks-with-ref-level)          n-ref (apply +                 (for [[_ rfs] filtered-ref-blocks]                   (count rfs)))]      (when (or (> n-ref 0)                (seq scheduled-or-deadlines)                (seq filter-state))        [:div.references.mt-6.flex-1.flex-row         [:div.content          (when (seq scheduled-or-deadlines)            (ui/foldable             [:h2.font-bold.opacity-50 "SCHEDULED AND DEADLINE"]             [:div.references-blocks.mb-6              (let [ref-hiccup (block/->hiccup scheduled-or-deadlines                                               {:id (str page-name "-agenda")                                                :ref? true                                                :group-by-page? true                                                :editor-box editor/box}                                               {})]                (content/content page-name                                 {:hiccup ref-hiccup}))]             {}))          (when (or (> n-ref 0)                    (seq filter-state))            (ui/foldable             [:div.flex.flex-row.flex-1.justify-between              [:h2.font-bold.opacity-50 (let []                                          (str n-ref " Linked Reference"                                               (when (> n-ref 1) "s")))]              [:a.opacity-50.hover:opacity-100.filter               {:title "Filter"                :on-click #(state/set-modal! (filter-dialog filters-atom references page-name))}               (svg/filter-icon (cond                                  (empty? filter-state) nil                                  (every? true? (vals filter-state)) "text-green-400"                                  (every? false? (vals filter-state)) "text-red-400"                                  :else "text-yellow-400"))]]             [:div.references-blocks              (let [ref-hiccup (block/->hiccup filtered-ref-blocks                                               {:id page-name                                                :ref? true                                                :breadcrumb-show? true                                                :group-by-page? true                                                :editor-box editor/box                                                :filters filters}                                               {})]                (content/content page-name                                 {:hiccup ref-hiccup}))]             {}))]]))))(rum/defcs unlinked-references-aux  < rum/reactive db-mixins/query  {:wrap-render   (fn [render-fn]     (fn [state]       (reset! (second (:rum/args state))               (apply +                      (for [[_ rfs]                            (db/get-page-unlinked-references                             (first (:rum/args state)))]                        (count rfs))))       (render-fn state)))}  [state page-name n-ref]  (let [ref-blocks (db/get-page-unlinked-references page-name)]    [:div.references-blocks     (let [ref-hiccup (block/->hiccup ref-blocks                                      {:id (str page-name "-unlinked-")                                       :ref? true                                       :group-by-page? true                                       :editor-box editor/box}                                      {})]       (content/content page-name                        {:hiccup ref-hiccup}))]))(rum/defcs unlinked-references < rum/reactive  (rum/local nil ::n-ref)  [state page-name]  (let [n-ref (get state ::n-ref)]    (when page-name      (let [page-name (string/lower-case page-name)]        [:div.references.mt-6.flex-1.flex-row         [:div.content.flex-1          (ui/foldable           [:h2.font-bold {:style {:opacity "0.3"}}            (if @n-ref              (str @n-ref " Unlinked Reference" (when (> @n-ref 1)                                                  "s"))              "Unlinked References")]           (fn [] (unlinked-references-aux page-name n-ref))           {:default-collapsed? true})]]))))
 |