diff --git a/.gitignore b/.gitignore
index 22d6a481..ae81b840 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,3 +8,5 @@ pom.xml.asc
*.class
/.lein-*
/.nrepl-port
+/resources/public/js/compiled
+*.log
diff --git a/Dockerfile b/Dockerfile
index 59f3cefd..b8e1d7cd 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,3 +1,6 @@
-FROM tomcat:9.0-jre8-alpine
-RUN 'apk add poppler-utils'
-COPY target/auto-ap.war /usr/local/tomcat
+FROM openjdk:8-jre-alpine
+RUN apk update
+RUN apk add poppler
+RUN apk add poppler-utils
+COPY target/auto-ap-0.1.0-SNAPSHOT-standalone.jar /usr/local/
+CMD java -jar /usr/local/auto-ap-0.1.0-SNAPSHOT-standalone.jar
diff --git a/project.clj b/project.clj
index 104ad572..3333531b 100644
--- a/project.clj
+++ b/project.clj
@@ -3,11 +3,71 @@
:url "http://example.com/FIXME"
:min-lein-version "2.0.0"
:dependencies [[org.clojure/clojure "1.8.0"]
+ [org.clojure/clojurescript "1.9.908"]
+ [reagent "0.7.0"]
+ [re-frame "0.10.2"]
[compojure "1.6.0"]
+ [secretary "1.2.3"]
[ring/ring-defaults "0.2.1"]
- [ring/ring-json "0.4.0"]]
- :plugins [[lein-ring "0.9.7"]]
+ [ring/ring-json "0.4.0"]
+ [ring "1.4.0"]
+ [yogthos/config "0.8"]]
+ :plugins [[lein-ring "0.9.7"]
+ [lein-cljsbuild "1.1.5"]]
+ :clean-targets ^{:protect false} ["resources/public/js/compiled" "target"]
:ring {:handler auto-ap.handler/app}
+ :source-paths ["src/clj"]
+
+ :figwheel {:css-dirs ["resources/public/css"]
+ :ring-handler auto-ap.handler/app}
+
+ :aliases {"dev" ["do" "clean"
+ ["pdo" ["figwheel" "dev"]]]
+ "build" ["do" "clean"
+ ["cljsbuild" "once" "min"]]}
+
:profiles
- {:dev {:dependencies [[javax.servlet/servlet-api "2.5"]
- [ring/ring-mock "0.3.0"]]}})
+ {:dev
+ {:dependencies [[binaryage/devtools "0.9.4"]
+ [javax.servlet/servlet-api "2.5"]
+ [figwheel-sidecar "0.5.13"]
+ [com.cemerick/piggieback "0.2.2"]]
+
+ :plugins [[lein-figwheel "0.5.13"]
+ [lein-pdo "0.1.1"]]}}
+
+ :cljsbuild
+ {:builds
+ [{:id "dev"
+ :source-paths ["src/cljs"]
+ :figwheel {:on-jsload "auto-ap.core/mount-root"}
+ :compiler {:main auto-ap.core
+ :output-to "resources/public/js/compiled/app.js"
+ :output-dir "resources/public/js/compiled/out"
+ :asset-path "js/compiled/out"
+ :source-map-timestamp true
+ :preloads [devtools.preload]
+ :external-config {:devtools/config {:features-to-install :all}}
+ }}
+
+ {:id "min"
+ :source-paths ["src/cljs"]
+ :jar true
+ :compiler {:main auto-ap.core
+ :output-to "resources/public/js/compiled/app.js"
+ :optimizations :advanced
+ :closure-defines {goog.DEBUG false}
+ :pretty-print false}}
+
+
+ ]}
+
+ :main auto-ap.server
+
+ :aot [auto-ap.server]
+
+ :uberjar-name "auto-ap.jar"
+
+ #_#_:prep-tasks [["cljsbuild" "once" "min"]"compile"])
+
+;;
diff --git a/resources/public/index.html b/resources/public/index.html
index c1b32626..e5211426 100644
--- a/resources/public/index.html
+++ b/resources/public/index.html
@@ -1,37 +1,331 @@
-
-
-
-
-
-
-
Invoice Parsing Demo
-
-
Found invoices:
-
-
+
+
+
+
+
+
+
Auto AP
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
diff --git a/src/auto_ap/handler.clj b/src/clj/auto_ap/handler.clj
similarity index 72%
rename from src/auto_ap/handler.clj
rename to src/clj/auto_ap/handler.clj
index c3779792..3ceff4bb 100644
--- a/src/auto_ap/handler.clj
+++ b/src/clj/auto_ap/handler.clj
@@ -9,15 +9,18 @@
[ring.middleware.json :refer [wrap-json-response]]))
(defroutes app-routes
+ (GET "/hi" [] "hello")
(GET "/" [] (response/resource-response "index.html" {:root "public"}))
(POST "/pdf-upload"
{{ files "file"} :params :as params}
(let [{:keys [filename tempfile]} (second files)]
- (io/copy tempfile (io/file "resources" "public" filename))
- (for [{:keys [total date invoice-number customer-identifier]} (parse/parse-file (str "resources/public/" filename))]
- (do
- (println (str "An invoice #" invoice-number " on " date " for " total))
- (str "An invoice for customer " customer-identifier " #" invoice-number " on " date " for " total )))))
+ (println tempfile)
+ #_(io/copy tempfile (io/file "resources" "public" filename))
+ (for [{:keys [total date invoice-number customer-identifier]} (parse/parse-file (.getPath tempfile))]
+ {"customer-identifier" customer-identifier
+ "invoice-number" invoice-number
+ "date" date
+ "total" total})))
(route/resources "/")
(route/not-found "Not Found"))
diff --git a/src/auto_ap/parse.clj b/src/clj/auto_ap/parse.clj
similarity index 100%
rename from src/auto_ap/parse.clj
rename to src/clj/auto_ap/parse.clj
diff --git a/src/clj/auto_ap/server.clj b/src/clj/auto_ap/server.clj
new file mode 100644
index 00000000..eccebb99
--- /dev/null
+++ b/src/clj/auto_ap/server.clj
@@ -0,0 +1,9 @@
+(ns auto-ap.server
+ (:require [auto-ap.handler :refer [app]]
+ [config.core :refer [env]]
+ [ring.adapter.jetty :refer [run-jetty]])
+ (:gen-class))
+
+ (defn -main [& args]
+ (let [port (Integer/parseInt (or (env :port) "3000"))]
+ (run-jetty app {:port port :join? false})))
diff --git a/src/cljs/auto_ap/config.cljs b/src/cljs/auto_ap/config.cljs
new file mode 100644
index 00000000..82f3cdf7
--- /dev/null
+++ b/src/cljs/auto_ap/config.cljs
@@ -0,0 +1,4 @@
+(ns auto-ap.config)
+
+(def debug?
+ ^boolean goog.DEBUG)
diff --git a/src/cljs/auto_ap/core.cljs b/src/cljs/auto_ap/core.cljs
new file mode 100644
index 00000000..cc002ea1
--- /dev/null
+++ b/src/cljs/auto_ap/core.cljs
@@ -0,0 +1,23 @@
+(ns auto-ap.core
+ (:require [reagent.core :as reagent]
+ [re-frame.core :as re-frame]
+ [auto-ap.events :as events]
+ [auto-ap.views :as views]
+ [auto-ap.config :as config]))
+
+
+(defn dev-setup []
+ (when config/debug?
+ (enable-console-print!)
+ (println "dev mode")))
+
+(defn mount-root []
+ (re-frame/clear-subscription-cache!)
+ (reagent/render [views/main-panel]
+ (.getElementById js/document "app")))
+
+(defn ^:export init []
+ (re-frame/dispatch-sync [::events/initialize-db])
+ (dev-setup)
+
+ (mount-root))
diff --git a/src/cljs/auto_ap/db.cljs b/src/cljs/auto_ap/db.cljs
new file mode 100644
index 00000000..364ecb0e
--- /dev/null
+++ b/src/cljs/auto_ap/db.cljs
@@ -0,0 +1,5 @@
+(ns auto-ap.db)
+
+(def default-db
+ {:company {:name "Campbell brewery"}
+ :invoices #{}})
diff --git a/src/cljs/auto_ap/events.cljs b/src/cljs/auto_ap/events.cljs
new file mode 100644
index 00000000..10e8a5d1
--- /dev/null
+++ b/src/cljs/auto_ap/events.cljs
@@ -0,0 +1,13 @@
+(ns auto-ap.events
+ (:require [re-frame.core :as re-frame]
+ [auto-ap.db :as db]))
+
+(re-frame/reg-event-db
+ ::initialize-db
+ (fn [_ _]
+ db/default-db))
+
+(re-frame/reg-event-db
+ ::imported-invoices
+ (fn [db [_ new-invoices]]
+ (update-in db [:invoices] into new-invoices)))
diff --git a/src/cljs/auto_ap/subs.cljs b/src/cljs/auto_ap/subs.cljs
new file mode 100644
index 00000000..b312f925
--- /dev/null
+++ b/src/cljs/auto_ap/subs.cljs
@@ -0,0 +1,13 @@
+(ns auto-ap.subs
+ (:require [re-frame.core :as re-frame]))
+
+(re-frame/reg-sub
+ ::name
+ (fn [db]
+ (:name (:company db))))
+
+
+(re-frame/reg-sub
+ ::invoices
+ (fn [db]
+ (:invoices db)))
diff --git a/src/cljs/auto_ap/views.cljs b/src/cljs/auto_ap/views.cljs
new file mode 100644
index 00000000..4585a35d
--- /dev/null
+++ b/src/cljs/auto_ap/views.cljs
@@ -0,0 +1,149 @@
+(ns auto-ap.views
+ (:require [re-frame.core :as re-frame]
+ [reagent.core :as reagent]
+ [auto-ap.subs :as subs]
+ [auto-ap.events :as events]))
+
+(def dropzone
+ (with-meta
+ (fn []
+ [:form {:action "/pdf-upload" :class ".dropzone"}
+ [:div {:class "card"}
+ [:div {:class "card-header"}
+ [:span {:class "card-header-title"} "Upload Invoices"]]
+ [:div {:class "card-content"}
+ [:span {:class "icon"}
+ [:i {:class "fa fa-cloud-download"}]]
+ "Drop invoice pdfs here"
+ [:input {:type "file", :name "file", :style {:display "none"}}]]]])
+ {:component-did-mount (fn [this]
+ (-> (js/$ (reagent/dom-node this))
+ (.dropzone (clj->js {:init (fn []
+ (this-as t
+ (.on t "success" (fn [_ files]
+ (re-frame/dispatch [::events/imported-invoices (js->clj (.parse js/JSON files))])
+ ))))
+ :url "/pdf-upload"}))))})
+ )
+
+(defn main-panel []
+ (let [name (re-frame/subscribe [::subs/name])
+ invoices (re-frame/subscribe [::subs/invoices])]
+ (println name)
+ [:div
+ [:nav {:class "navbar has-shadow"}
+ [:div {:class "container"}
+ [:div {:class "navbar-brand"}
+ [:a {:class "navbar-item", :href "../"}
+ [:h1 (str "Auto-ap - " @name)]]
+ [:div {:class "navbar-burger burger", :data-target "navMenu"}
+ [:span]
+ [:span]
+ [:span]]]
+ [:div {:id "navMenu", :class "navbar-menu"}
+ [:div {:class "navbar-end"}
+ [:div {:class "navbar-item has-dropdown is-active"}
+ [:a {:class "navbar-link login"} ]
+ [:div {:class "navbar-dropdown", :style {:display "none"}}
+ [:a {:class "navbar-item"} ]
+ [:a {:class "navbar-item"} ]
+ [:a {:class "navbar-item"} ]
+ [:hr {:class "navbar-divider"}]
+ [:div {:class "navbar-item"} ]]]]]]]
+ [:div {:class "columns", :id "mail-app"}
+ [:aside {:class "column is-narrow aside hero is-fullheight"}
+ [:div.left-nav
+ [:div {:class "compose has-text-centered"}
+ [:a {:class "button is-danger is-block is-bold"}
+ [:span {:class "compose"} "New Invoice"]]]
+ [:div {:class "main"}
+ [:a {:href "#", :class "item active"}
+ [:span {:class "icon"}
+ [:i {:class "fa fa-inbox"}]]
+ [:span {:class "name"} "Upload\n Invoices"]]
+ [:a {:href "#", :class "item"}
+ [:span {:class "icon"}
+ [:i {:class "fa fa-star"}]]
+ [:span {:class "name"} "Unpaid Invoices"]]
+ [:a {:href "#", :class "item"}
+ [:span {:class "icon"}
+ [:i {:class "fa fa-envelope-o"}]]
+ [:span {:class "name"} "Paid Invoices"]]]]]
+ [:div {:class "column messages hero is-fullheight", :id "message-feed"}
+ [:div {:class "inbox-messages"}
+ [dropzone]
+
+ [:div {:class "section"}]
+ [:div {:class "card found-invoices", :style {:display (if (seq @invoices) "block" "none")}}
+ [:div {:class "card-header"}
+ [:span {:class "card-header-title"} "Found Invoices"]]
+ [:div {:class "card-content"}
+ [:table {:class "table", :style {:width "100%"}}
+ [:thead
+ [:tr
+ [:th "Customer"]
+ [:th "Invoice #"]
+ [:th "Date"]
+ [:th "Amount"]]]
+ [:tbody (for [{:strs [customer-identifier invoice-number date total]} @invoices]
+ ^{:key (str customer-identifier "-" invoice-number)}
+ [:tr
+ [:td customer-identifier]
+ [:td invoice-number]
+ [:td date]
+ [:td total]])]]]]]]]
+ [:footer {:class "footer"}
+ [:div {:class "container"}
+ [:div {:class "content has-text-centered"}
+ [:p
+ [:strong "Auto-AP"]"by "
+ [:a {:href "https://github.com/"} "Integreat"]"."]
+ [:p
+ [:a {:class "icon", :href "https://github.com/dansup/bulma-templates"}
+ [:i {:class "fa fa-github"}]]]]]]]))
+
+
+
+;;
+;;
+