forked from intermine/im-tables-3
/
save.cljs
128 lines (119 loc) · 5.41 KB
/
save.cljs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
(ns im-tables.views.dashboard.save
(:require [re-frame.core :refer [subscribe dispatch]]
[reagent.core :as reagent]
[oops.core :refer [oget ocall ocall!]]
[inflections.core :refer [plural]]
[imcljs.path :as path :refer [walk class]]
[im-tables.components.bootstrap :refer [modal]]
[im-tables.utils :refer [on-event]]))
(defn join-with-arrows [col]
(clojure.string/join " > " col))
(defn save-dialog []
(let [dom-node (reagent/atom nil)]
(fn [state-atom details on-submit]
(let [submit-fn (fn [k] (when (= 13 (oget k :keyCode))
(on-submit)
(-> @dom-node js/$ (ocall :closest ".modal") (ocall :modal "hide"))))
change-fn (fn [kw e] (swap! state-atom assoc kw (oget e :target :value)))]
[:div.container-fluid
{:ref (fn [e] (when e (reset! dom-node e)))}
[:div.form.save-body
[:div.form-group
[:label "Name"]
[:input.form-control.input-lg
{:value (get @state-atom :name)
:on-change (partial change-fn :name)
:on-key-up submit-fn}]
[:div.optional-attributes
[:hr]
[:span "Optional attributes"]]
[:label "Description"]
[:input.form-control
{:value (get @state-atom :description)
:on-change (partial change-fn :description)
:on-key-up submit-fn
:placeholder "Enter a description"}]]]]))))
(defn save-footer []
(fn [loc state {:keys [picking?] :as details} on-submit]
[:div.btn-toolbar.pull-right
[:button.btn.btn-default
{:on-click (fn [_evt]
(dispatch [:modal/close loc])
(when picking?
(dispatch [:pick-items/stop loc])))}
"Cancel"]
[:button.btn.btn-raised.btn-success
{:on-click on-submit}
"Save"]]))
(defn generate-dialog [loc {:keys [type count query picking?] :as details}]
(let [state (reagent/atom {:name (str (name type) " List (" (.toString (js/Date.)) ")")
:description ""})
on-submit (fn []
(dispatch [:imt.io/save-list loc (:name @state) (:query details) @state])
(dispatch [:modal/close loc])
(when picking?
(dispatch [:pick-items/stop loc])))]
{:header [:h4 (str "Save a list of " (:count details) " "
;; It's possible that `count` is the string "..." if
;; the webservice hasn't responded yet.
(if (and (number? count) (< count 2))
(name type)
(plural (name type))))]
:body [save-dialog state details on-submit]
:footer [save-footer loc state details on-submit]
:no-fade picking?}))
(defn serialize-path [model path]
(let [[root & remaining] (remove nil? (map :displayName (walk model path)))]
(if remaining
(clojure.string/join " > " (conj (map plural remaining) root))
(plural root))))
(defn menu-heading [loc]
(let [model (subscribe [:assets/model loc])]
(fn [loc class details]
[:li
[:span
[:h4 class]
(into [:ul]
(map (fn [[path query]]
[:li [:a {:on-click
#(dispatch [:modal/open loc
(generate-dialog loc
{:query query
:type class})])}
(serialize-path @model path)]]) details))]])))
(defn save-menu [loc _model _path _details]
(let [counts (subscribe [:main/query-parts-counts loc])]
(fn [loc model path {:keys [query]}]
(let [count (get @counts path "...")]
[:li {:on-click
#(dispatch [:modal/open loc
(generate-dialog loc
{:query query
:count count
:type (name (path/class model path))})])}
[:a [:strong (serialize-path model path)] (str " (" count ")")]]))))
(defn main [loc]
(let [model (subscribe [:assets/model loc])
query-parts (subscribe [:main/query-parts loc])
counts (subscribe [:main/query-parts-counts loc])]
(fn [loc]
[:div.dropdown
{:ref (on-event
"show.bs.dropdown"
#(when (nil? @counts)
;; This will only run for the initial query. For any
;; subsequent queries, we'll `:main/count-deconstruction`
;; alongside the query.
(doseq [event (map (fn [[part details]]
[:main/count-deconstruction loc part details])
@query-parts)]
(dispatch event))))}
[:button.btn.btn-default.dropdown-toggle
{:data-toggle "dropdown"} [:span [:i.fa.fa-cloud-upload] " Save List"]]
(-> [:ul.dropdown-menu]
(into (map-indexed (fn [idx [path details]]
[save-menu loc @model path details])
@query-parts))
(conj [:hr]
[:li {:on-click #(dispatch [:pick-items/start loc])}
[:a "Pick items from the table"]]))])))