diff --git a/src/cljs/ulysses/components/word_cloud.cljs b/src/cljs/ulysses/components/word_cloud.cljs new file mode 100644 index 0000000..0d55e1c --- /dev/null +++ b/src/cljs/ulysses/components/word_cloud.cljs @@ -0,0 +1,40 @@ +(ns ulysses.components.word-cloud + (:require [ulysses.utils :refer [map-subels]])) + +;; ---------------------------------------------------------------------------- +;; helpers +;; ---------------------------------------------------------------------------- + +(defn normalize [keywords] + (let [scores (map (fn [k] (get-in k [:pivot :score])) keywords) + s-min (or (apply min scores) 0) + s-max (or (apply max scores) 100) + denom (- s-max s-min)] + (map + (fn [kw] + (assoc kw :nscore + (/ (- (get-in kw [:pivot :score]) s-min) + denom))) + keywords))) + +(defn normalize-sort-take [n keywords] + (->> keywords + (normalize) + (sort-by :nscore) + (reverse) + (take n))) + +;; ---------------------------------------------------------------------------- +;; sub-components +;; ---------------------------------------------------------------------------- + +(defn word-cloud-keyword [{:keys [name nscore]}] + [:a.keyword {:class (str "weight-" (Math/round (* 100 nscore)))} name]) + +;; ---------------------------------------------------------------------------- +;; main +;; ---------------------------------------------------------------------------- + +(defn word-cloud [n keywords] + [:div.word-cloud + (map-subels word-cloud-keyword (normalize-sort-take n keywords))]) diff --git a/src/cljs/ulysses/db.cljs b/src/cljs/ulysses/db.cljs index 038cee7..aadebb2 100644 --- a/src/cljs/ulysses/db.cljs +++ b/src/cljs/ulysses/db.cljs @@ -75,9 +75,5 @@ :builder-filters {:faculty-title-set ["director"] :faculty-years-uconn 0} - ;; ------------------------------------------------------------------------- - ;; interface - ;; ------------------------------------------------------------------------- - - ; example - :example nil}) + ; user workspace-faculty hover (id) + :builder-faculties-workspace-hover nil}) diff --git a/src/cljs/ulysses/handlers.cljs b/src/cljs/ulysses/handlers.cljs index 582df38..b51f261 100644 --- a/src/cljs/ulysses/handlers.cljs +++ b/src/cljs/ulysses/handlers.cljs @@ -259,3 +259,17 @@ (dispatch [:request-faculties-pool]) (assoc-in db [:builder-filters :faculty-years-uconn] (or (str->int years-uconn) 0)))) + +;; builder faculty workspace hover + +(register-handler + :builder-faculties-workspace-hover + (fn [db [_ faculty-id]] + (assoc db :builder-faculties-workspace-hover + faculty-id))) + +(register-handler + :nil-builder-faculties-workspace-hover + (fn [db _] + (assoc db :builder-faculties-workspace-hover + nil))) diff --git a/src/cljs/ulysses/pages/builder.cljs b/src/cljs/ulysses/pages/builder.cljs index 14ca4fb..f4b4ddb 100644 --- a/src/cljs/ulysses/pages/builder.cljs +++ b/src/cljs/ulysses/pages/builder.cljs @@ -1,6 +1,7 @@ (ns ulysses.pages.builder (:require [re-frame.core :as re-frame :refer [subscribe dispatch]] [ulysses.components.basic :refer [hink link loading-or-no-results fa]] + [ulysses.components.word-cloud :refer [word-cloud]] [ulysses.utils :refer [map-subels map-lookup str->int]] [reagent.core :as r] [clojure.string :as string] @@ -68,6 +69,8 @@ (defn workspace-row [faculty] (let [{:keys [id name title year_hired]} faculty] [:tr.faculty-row + {:on-mouse-over #(dispatch [:builder-faculties-workspace-hover id]) + :on-mouse-leave #(dispatch [:nil-builder-faculties-workspace-hover])} [:td.first-col [hink (partial dispatch [:remove-working-faculty id]) @@ -79,7 +82,9 @@ (defn workspace [faculties] (if (empty? faculties) - [loading-or-no-results] + [loading-or-no-results + :not-found-message + "Your workspace is empty. Add faculty from the pool to the right."] [:div.faculties-pool.table-responsive [:table.table.table-striped.table-bordered.table-sm [:thead @@ -117,6 +122,7 @@ (defn builder-panel [grant faculties faculty-titles faculties-pool faculties-workspace + faculties-workspace-hover builder-filters] [:div.builder-panel [sidebar faculty-titles builder-filters] @@ -126,7 +132,9 @@ [:h3 "Working Team"] [workspace (map-lookup faculties faculties-workspace)]] [:div.inner - [:h3 "Word Cloud"]]] + [:h3 "Word Cloud"] + (when faculties-workspace-hover + [word-cloud 20 (:keywords faculties-workspace-hover)])]] [:div.builder-panel-half-section [:div.inner [:h3 "Results"] @@ -142,6 +150,7 @@ faculty-titles (subscribe [:faculty-titles]) faculties-pool (subscribe [:builder-faculties-pool]) faculties-workspace (subscribe [:builder-faculties-workspace]) + faculties-workspace-hover (subscribe [:builder-faculties-workspace-hover]) last-id (atom nil)] (r/create-class {:component-will-mount @@ -171,12 +180,13 @@ ft @faculty-titles fp @faculties-pool fw @faculties-workspace + fh @faculties-workspace-hover bf @builder-filters _ @page-with-args] (if op [:div [:h3.text-xs-center.mb-15 (:title op)] - [:div [builder-panel op fa ft fp fw bf]]] + [:div [builder-panel op fa ft fp fw fh bf]]] [loading-or-no-results :not-found-message "The requested grant opportunity was not found."])))}))) diff --git a/src/cljs/ulysses/pages/profile.cljs b/src/cljs/ulysses/pages/profile.cljs index a8283e5..36009ba 100644 --- a/src/cljs/ulysses/pages/profile.cljs +++ b/src/cljs/ulysses/pages/profile.cljs @@ -1,8 +1,9 @@ (ns ulysses.pages.profile (:require [re-frame.core :as re-frame :refer [subscribe dispatch]] [ulysses.routes :as routes] - [ulysses.utils :refer [map-subels str->int normalize-keyword-scores]] + [ulysses.utils :refer [str->int]] [ulysses.components.basic :refer [label loading-or-no-results]] + [ulysses.components.word-cloud :refer [word-cloud]] [reagent.core :as r])) ;; helpers ----------------------------------------- @@ -12,14 +13,6 @@ ;; helper sub-components --------------------------- -(defn word-cloud-keyword [{:keys [name nscore]}] - [:a.keyword {:class (str "weight-" (Math/round (* 100 nscore)))} name]) - -(defn word-cloud [keywords] - (let [norm (->> keywords normalize-keyword-scores (sort-by :nscore) reverse (take 50))] - [:div.word-cloud - (map-subels word-cloud-keyword norm)])) - (defn profile [{:keys [name title department year_hired keywords] :as faculty}] [:div.container [:div.row @@ -31,7 +24,7 @@ [label :default department] " " [label :default "hired in " year_hired]] - [word-cloud keywords]]]]) + [word-cloud 50 keywords]]]]) ;; main -------------------------------------------- diff --git a/src/cljs/ulysses/subs.cljs b/src/cljs/ulysses/subs.cljs index 4af143a..fd96e2b 100644 --- a/src/cljs/ulysses/subs.cljs +++ b/src/cljs/ulysses/subs.cljs @@ -97,3 +97,15 @@ :builder-filters (fn [db _] (reaction (:builder-filters @db)))) + +;; ---------------------------------------------------------------------------- +;; derived data +;; ---------------------------------------------------------------------------- + +(register-sub + :builder-faculties-workspace-hover + (fn [db _] + (reaction + (let [{:keys [faculties builder-faculties-workspace-hover db]} @db] + (when builder-faculties-workspace-hover + (get faculties builder-faculties-workspace-hover)))))) diff --git a/src/cljs/ulysses/utils.cljs b/src/cljs/ulysses/utils.cljs index bb7fdbd..f209df9 100644 --- a/src/cljs/ulysses/utils.cljs +++ b/src/cljs/ulysses/utils.cljs @@ -3,7 +3,7 @@ (:require [clojure.string :as string] [clojure.walk :refer [keywordize-keys]] [clojure.set :refer [rename-keys]] - [cljs.core.async :refer [chan put!