|
| 1 | +(ns clojurescript.flow-monitor-ui.components.log-modal |
| 2 | + (:require |
| 3 | + [clojurescript.flow-monitor-ui.utils.helpers :refer [>dis <sub]] |
| 4 | + [cljs.reader :as reader] |
| 5 | + [clojurescript.flow-monitor-ui.events :as events] |
| 6 | + [reagent.core :as r] |
| 7 | + [re-frame.core :as rf] |
| 8 | + [clojurescript.flow-monitor-ui.global :refer [global-state send-socket-data]] |
| 9 | + [clojure.string :as str])) |
| 10 | + |
| 11 | +(def modal-state (r/atom {:display-type :data |
| 12 | + :filter-text ""})) |
| 13 | + |
| 14 | +(rf/reg-sub |
| 15 | + ::log-modal-visible? |
| 16 | + (fn [db _] |
| 17 | + (-> db :routes :components :log-modal-visible?))) |
| 18 | + |
| 19 | +(rf/reg-event-fx |
| 20 | + ::set-log-modal-visibility |
| 21 | + (fn [{:keys [db]} [_ state]] |
| 22 | + {:db (assoc-in db [:routes :components :log-modal-visible?] state)})) |
| 23 | + |
| 24 | +(defn message-table [filtered-messages] |
| 25 | + (let [messages (if (string? (first filtered-messages)) |
| 26 | + (map reader/read-string filtered-messages) |
| 27 | + filtered-messages) |
| 28 | + columns (keys (first messages))] |
| 29 | + [:div.table-container |
| 30 | + [:table.data-table |
| 31 | + [:thead |
| 32 | + [:tr |
| 33 | + (for [column columns] |
| 34 | + ^{:key (name column)} |
| 35 | + [:th (name column)])]] |
| 36 | + [:tbody |
| 37 | + (for [[idx row] (map-indexed vector messages)] |
| 38 | + ^{:key idx} |
| 39 | + [:tr |
| 40 | + (for [column columns] |
| 41 | + ^{:key (str idx "-" (name column))} |
| 42 | + [:td (get row column)])])]]])) |
| 43 | + |
| 44 | +(defn message-data [messages] |
| 45 | + [:div#log-display |
| 46 | + (for [[idx log] (map-indexed vector messages)] |
| 47 | + ^{:key idx} |
| 48 | + [:pre (str log)])]) |
| 49 | + |
| 50 | +(defn display-select |
| 51 | + [{:keys [options id class-name]}] |
| 52 | + [:select.dropdown-select |
| 53 | + {:id id |
| 54 | + :class class-name |
| 55 | + :value (:display-type @modal-state) |
| 56 | + :on-change (fn [evt] (let [new-val (keyword (.. evt -target -value))] |
| 57 | + (swap! modal-state assoc-in [:display-type] new-val)))} |
| 58 | + (for [{:keys [value label]} options] |
| 59 | + ^{:key value} |
| 60 | + [:option {:value value} label])]) |
| 61 | + |
| 62 | +(defn filter-input [full?] |
| 63 | + [:div.filter-container {:class (when full? "filter-container-full")} |
| 64 | + [:input {:type "text" |
| 65 | + :placeholder "Regex Filter..." |
| 66 | + :value (:filter-text @modal-state) |
| 67 | + :on-change (fn [e] |
| 68 | + (let [filter-str (.. e -target -value)] |
| 69 | + (swap! modal-state assoc-in [:filter-text] filter-str)))}]]) |
| 70 | + |
| 71 | +(defn log-modal [] |
| 72 | + (let [modal-visible? (<sub [::log-modal-visible?]) |
| 73 | + messages (:messages @global-state) |
| 74 | + homogeneous? (= 1 (count (set (map keys messages)))) |
| 75 | + filter-text (:filter-text @modal-state) |
| 76 | + filtered-messages (if (str/blank? filter-text) [] (filter #(re-find (re-pattern filter-text) %) (map str messages))) |
| 77 | + display-messages (if (not-empty filtered-messages) filtered-messages messages)] |
| 78 | + [:div.modal-overlay {:class (when modal-visible? "is-visible")} |
| 79 | + [:div.modal |
| 80 | + [:div.modal-header |
| 81 | + [:div#modal-title "Logs"] |
| 82 | + [:div#close-button {:on-click (fn [evt] |
| 83 | + (.remove (.-classList (.-body js/document)) "modal-open") |
| 84 | + (>dis [::set-log-modal-visibility false]))} "X"]] |
| 85 | + [:div.modal-body.modal-body-pad |
| 86 | + [:div.controls-row |
| 87 | + [filter-input (not homogeneous?)] |
| 88 | + (when homogeneous? [display-select {:options [{:value "data" :label "data"} {:value "table" :label "table"}]}])] |
| 89 | + [:div.panel-contents |
| 90 | + (if homogeneous? |
| 91 | + (case (:display-type @modal-state) |
| 92 | + :data [message-data display-messages] |
| 93 | + :table [message-table display-messages]) |
| 94 | + [message-data display-messages])]]]])) |
| 95 | + |
0 commit comments