Created
August 25, 2015 13:52
-
-
Save alexfaber2011/f8937c483668a6d9e7f2 to your computer and use it in GitHub Desktop.
taste of clojurescript and reagent
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| (ns informacast-csv.core | |
| (:require [informacast-csv.informormacast-communicator :as communicator] | |
| [informacast-csv.zip-worker :as zip-worker] | |
| [reagent.core :as reagent] | |
| [reagent.session :as session] | |
| [reagent-forms.core :refer [bind-fields]] | |
| [goog.history.EventType :as EventType] | |
| [goog.events :as events] | |
| [secretary.core :as secretary :refer-macros [defroute]]) | |
| (:import goog.History)) | |
| ;; May want to remove in production | |
| (enable-console-print!) | |
| ;; ------------------------- | |
| ;; Navigation | |
| (session/put! :enabled-pages #{:ip-address}) | |
| (defn enable-pages | |
| [& page-ids] | |
| (session/put! :enabled-pages (apply #(conj (session/get :enabled-pages) %) page-ids))) | |
| (defn disable-pages | |
| [& page-ids] | |
| (session/put! :enabled-pages (apply #(disj (session/get :enabled-pages) %) page-ids))) | |
| ;; ------------------------- | |
| ;; Components( | |
| (def ip-doc (reagent/atom {})) | |
| (def credentials-doc (reagent/atom {})) | |
| (def import-doc (reagent/atom {})) | |
| (def is-loading (reagent/atom false)) | |
| (defn toggle-loading-state [loading] | |
| (reset! is-loading loading)) | |
| (defn submit-button [] | |
| [:button.btn.btn-primary {:disabled @is-loading :type "submit"} (if @is-loading "Loading..." "Submit")]) | |
| (def ip-form-template | |
| [:form {:on-submit (fn [e] | |
| (toggle-loading-state true) | |
| (.preventDefault e) | |
| (communicator/ping (:ip-address @ip-doc) | |
| #(do | |
| (enable-pages :credentials) | |
| (secretary/dispatch! "#/credentials")) | |
| #(do | |
| (disable-pages :credentials :import) | |
| (js/alert "Unable to find InformaCast server at specified URL")) | |
| #(toggle-loading-state false)))} | |
| [:div.form-group | |
| [:label {:for :ip-address :style {:font-size "16pt"}} "IP ADDRESS:PORT"] | |
| [:input.form-control.narrow {:field :text | |
| :id :ip-address | |
| :style {:text-align "center"}}]] | |
| [submit-button]]) | |
| (defn ip-address-component [] | |
| (fn [] | |
| [:div | |
| [:p.visible-md (when (not (clojure.string/blank? (:ip-address @ip-doc))) | |
| (str "The route we will ping to see if your server is online is: " (communicator/interpolate-ip-address (:ip-address @ip-doc))))] | |
| [bind-fields ip-form-template ip-doc]])) | |
| (def credentials-form-template | |
| [:form {:on-submit (fn [e] | |
| (toggle-loading-state true) | |
| (.preventDefault e) | |
| (communicator/authenticate | |
| (:username @credentials-doc) | |
| (:password @credentials-doc) | |
| #(do | |
| (enable-pages :import) | |
| (secretary/dispatch! "#/import")) | |
| #(do | |
| (disable-pages :import) | |
| (js/alert %)) | |
| #(toggle-loading-state false)))} | |
| [:div.form-group | |
| [:label {:for :username :style {:font-size "16pt"}} "Credentials"] | |
| [:input.form-control.narrow {:field :text | |
| :id :username | |
| :placeholder "user name" | |
| :style {:text-align "center"}}] | |
| [:input.form-control.narrow {:field :password | |
| :placeholder "password" | |
| :id :password | |
| :style {:text-align "center"}}]] | |
| [submit-button]]) | |
| (defn credentials-component [] | |
| (fn [] | |
| [:div | |
| [bind-fields credentials-form-template credentials-doc]])) | |
| (def import-form-template | |
| [:form {:on-submit (fn [e] | |
| (.preventDefault e) | |
| (println "SUBMITTED"))} | |
| [:div.form-group | |
| [:label {:for :username :style {:font-size "16pt"}} "IMPORT YOUR .ZIP FILE"] | |
| [:input.form-control.narrow {:type :file | |
| :id :file-input | |
| :style {:text-align "center"} | |
| :on-change (fn [e] | |
| (let [file (first (array-seq (.. e -target -files))) | |
| file-reader (js/FileReader.)] | |
| (set! (.-onload file-reader) | |
| (fn [e] | |
| (zip-worker/start-working (-> e .-target .-result)))) | |
| (.readAsArrayBuffer file-reader file)) | |
| (enable-pages :results))}]] | |
| [:p "Process will begin immediately after selecting respective zip file"]]) | |
| (defn import-component [] | |
| (fn [] | |
| [:div | |
| [bind-fields import-form-template import-doc]])) | |
| (defn results-component [] | |
| [:div {:style {:max-height "500px" :overflow "scroll"}} | |
| [:h1 "RESULTS"] | |
| [:h3 "Successful Operations"] | |
| (for [operation-description (communicator/get-successful-operations)] | |
| [:h4 (str "Description: " operation-description)]) | |
| (when (not (empty? (communicator/get-unsuccessful-operations))) | |
| [:div | |
| [:h3 "Unsuccessful Operations"] | |
| (for [operation-description (communicator/get-unsuccessful-operations)] | |
| [:pre | |
| [:h4 (str "Description" (:description operation-description))] | |
| [:p "fieldName: " [:code (get operation-description :field-name)]] | |
| [:p "fieldValue: " [:code (let [field-value (get operation-description :field-value)] | |
| (if field-value | |
| field-value | |
| "null"))]] | |
| [:p "messageType: " [:code (get operation-description :message-type)]] | |
| [:p "message: " [:code (get operation-description :message)]]])])]) | |
| (defn not-found-component [] | |
| [:h1 {:class "cover-heading"} "PAGE NOT FOUND"]) | |
| ;; ------------------------- | |
| ;; Navigation | |
| (def page-links [{:id :ip-address, :title "1 - IP Address", :url "#/", :component #'ip-address-component} | |
| {:id :credentials, :title "2 - Credentials", :url "#/credentials", :component #'credentials-component} | |
| {:id :import, :title "3 - Import", :url "#/import", :component #'import-component} | |
| {:id :results, :title "4 - Results", :url "#/results", :component #'results-component}]) | |
| (defn set-current-page [page-id] | |
| (if (= page-id :not-found) | |
| (do | |
| (session/put! :current-page #'not-found-component) | |
| (session/put! :active-link nil)) | |
| (do | |
| (session/put! :current-page (-> (filter #(= (:id %) page-id) page-links) | |
| first | |
| :component)) | |
| (session/put! :active-link page-id)))) | |
| (defn navigation [] | |
| [:div {:class "masthead clearfix"} | |
| [:div {:class "inner"} | |
| [:h3 {:class "masthead-brand"} "InformaCast Wizard"] | |
| [:nav | |
| [:ul {:class "nav masthead-nav"} | |
| (doall (for [link page-links] | |
| (let [link-enabled? (contains? (session/get :enabled-pages) (:id link))] | |
| [:li {:class (when (= (:id link) (session/get :active-link)) "active")} | |
| [:a {:href (if link-enabled? (:url link) "#") | |
| :style {:cursor (if link-enabled? "pointer" "not-allowed") :color (when-not link-enabled? "#FBC6D3")}} (:title link)]])))]]]]) | |
| ;; ------------------------- | |
| ;; BASE | |
| (defn page [] | |
| [:div.cover-container | |
| [navigation] | |
| [:div {:class "inner cover"} | |
| [(session/get :current-page)]]]) | |
| (defn render-app [] | |
| (reagent/render [page] | |
| (.getElementById js/document "app"))) | |
| ;; ------------------------- | |
| ;; History | |
| (defn- hook-browser-navigation! | |
| "Listens for html5 route changes and notifies secretary of the event" | |
| [] | |
| (doto (History.) | |
| (events/listen EventType/NAVIGATE #(secretary/dispatch! (.-token %))) | |
| (.setEnabled true))) | |
| ;; ------------------------- | |
| ;; Routes | |
| (secretary/set-config! :prefix "#") | |
| (set-current-page :ip-address) | |
| (defroute "/" [] (set-current-page :ip-address)) | |
| (defroute "/credentials" [] (set-current-page :credentials)) | |
| (defroute "/import" [] (set-current-page :import)) | |
| (defroute "/results" [] (set-current-page :results)) | |
| (defroute "*" [] (set-current-page :not-found)) | |
| (defn ^:export init | |
| "Initializes the application by wiring our html5 routing with secretary and rendering our react application" | |
| [] | |
| (.initializeTouchEvents js/React true) | |
| (hook-browser-navigation!) | |
| (render-app)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment