Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions resources/public/css/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -97,3 +97,17 @@ button.applied-facet:hover svg {
left: -1px;
top: 0px;
}

/* Indeterminate checkboxes -----
Style lifted directly from Bootstrap 5 but applied via a class instead of
setting the `indeterminate` attribute on checkbox elements (which can only
be done with js, there is no pure-html way), because getting a hold of
actual html dom elements and setting their attributes directly is "impure"
and therefore painful in reframe */

/* .form-check-input[type=checkbox]:indeterminate */
.indeterminate-checkbox {
background-color: #0d6efd;
border-color: #0d6efd;
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10h8'/%3e%3c/svg%3e");
}
27 changes: 26 additions & 1 deletion src/ook/reframe/codes/db/selection.cljs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
(ns ook.reframe.codes.db.selection
(:require
[meta-merge.core :as mm]))
[meta-merge.core :as mm]
[clojure.set :as set]
[ook.reframe.codes.db.disclosure :as disclosure]))

(defn- codelist? [option]
(nil? (:scheme option)))
Expand Down Expand Up @@ -37,6 +39,19 @@
(-> selection (get scheme) (get uri) boolean)
(and (contains? selection uri) (nil? (get selection uri)))))

(defn- all-child-uris [node]
(let [walk (fn walk* [node]
(cons (:ook/uri node)
(when-let [children (:children node)]
(when-not (= :no-children children)
(mapcat walk* children)))))]
(set (walk node))))

(defn indeterminate? [selected-uris option]
(let [walk (memoize all-child-uris)
all-child-uris (walk option)]
(boolean (seq (set/intersection selected-uris all-child-uris)))))

(defn toggle [facet option]
(if (option-selected? facet option)
(remove-from-selection facet option)
Expand All @@ -60,3 +75,13 @@
(update-in selection [scheme] disj uri))
current-selection
codes))

(defn all-selected-uris [db]
(let [selection (-> db :ui.facets/current :selection)]
(set
(reduce (fn [uris [scheme code-uris]]
(if (seq code-uris)
(concat uris code-uris)
(conj uris scheme)))
[]
selection))))
7 changes: 4 additions & 3 deletions src/ook/reframe/codes/view.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,18 @@
(common/with-react-keys children)])

(defn checkbox-input [{:keys [ook/uri label used] :as option}]
(let [selected? @(rf/subscribe [:ui.facets.current/option-selected? option])
(let [checked-state @(rf/subscribe [:ui.facets.current/checked-state option])
id (str (gensym (str uri "-react-id-")))]
[:<>
[:input.form-check-input.me-2
(cond-> {:type "checkbox"
:name "code"
:value uri
:id id
:checked selected?
:checked (= :checked checked-state)
:on-change #(rf/dispatch [:ui.event/toggle-selection option])}
(not used) (merge {:disabled true}))]
(not used) (assoc :disabled true)
(= :indeterminate checked-state) (assoc :class "indeterminate-checkbox"))]
[:label.form-check-label.d-inline {:for id} label]]))

(defn codelist-wrapper [codelist-uri code-tree]
Expand Down
15 changes: 12 additions & 3 deletions src/ook/reframe/subs.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,18 @@
(some-> db :ui.facets/current :selection)))

(rf/reg-sub
:ui.facets.current/option-selected?
:ui.facets.current/checked-state
(fn [db [_ option]]
(selection/option-selected? (:ui.facets/current db) option)))
(let [selected-uris (selection/all-selected-uris db)]
(cond
(selection/option-selected? (:ui.facets/current db) option)
:checked

(selection/indeterminate? selected-uris option)
:indeterminate

:else
:unchecked))))

(rf/reg-sub
:ui.facets.current/option-expanded?
Expand All @@ -49,7 +58,7 @@

(rf/reg-sub
:ui.facets.current/all-used-children-selected?
(fn [db [_ {:keys [scheme children] :as code}]]
(fn [db [_ {:keys [scheme children]}]]
(let [used-child-uris (->> children (filter :used) (map :ook/uri) set)
current-selection (-> db :ui.facets/current :selection (get scheme))]
(set/subset? used-child-uris current-selection))))
Expand Down
7 changes: 6 additions & 1 deletion test/ook/filters/selection_test.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,12 @@
(testing "unused codes are not selectable"
(is (= [] (qh/all-selected-labels)))
(eh/click-text "2-2 child 2")
(is (= [] (qh/all-selected-labels)))))
(is (= [] (qh/all-selected-labels))))

(testing "indeterminate select state"
(testing "selecting a code marks all of its parents as indeterminately selected"
(eh/click-text "2-2 child 1")
(is (= ["Codelist 2 Label" "2-1 child 2"] (qh/all-indeterminate-labels))))))

(setup/cleanup!))

Expand Down
3 changes: 3 additions & 0 deletions test/ook/test/util/query_helpers.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@
(defn all-selected-labels []
(all-text-content ".filters input[type='checkbox']:checked + label"))

(defn all-indeterminate-labels []
(all-text-content ".filters input[type='checkbox'].indeterminate-checkbox + label"))

(defn expanded-labels-under-label [label]
(-> label query-text .-parentNode (all-text-content selectable-code-label-query)))

Expand Down