Now a simple re-frame app
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -8,3 +8,5 @@ pom.xml.asc
|
||||
*.class
|
||||
/.lein-*
|
||||
/.nrepl-port
|
||||
/resources/public/js/compiled
|
||||
*.log
|
||||
|
||||
@@ -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
|
||||
|
||||
68
project.clj
68
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"])
|
||||
|
||||
;;
|
||||
|
||||
@@ -1,37 +1,331 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<script src="https://cdn.jsdelivr.net/npm/dropzone@5.2.0/dist/dropzone.min.js"></script>
|
||||
<script src="http://code.jquery.com/jquery-3.2.1.min.js" integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=" crossorigin="anonymous"></script>
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.6.1/css/bulma.css" />
|
||||
<style>.dz-error-mark { display:none} .dz-details {display:none}
|
||||
form { border: 3px solid lightgray; padding: 25px; width: 100%;}
|
||||
.dz-success-mark {display:none} </style>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="app" class="container">
|
||||
<h1>Invoice Parsing Demo</h1>
|
||||
<form action="/pdf-upload" id="my-dropzone">
|
||||
<h3>Drop invoice pdfs here</h3>
|
||||
<input type="file" name="file" style="display:none"/>
|
||||
</form>
|
||||
<h2 style="display:none">Found invoices:</h2>
|
||||
<ul>
|
||||
</ul>
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Auto AP</title>
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" integrity="sha256-eZrrJcwDc/3uDhsdt61sL2oOBY362qM3lon1gyExkL0=" crossorigin="anonymous" />
|
||||
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400,700" rel="stylesheet">
|
||||
<script src="https://cdn.auth0.com/js/lock/10.24/lock.min.js"></script>
|
||||
<!-- Bulma Version 0.6.0 -->
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.6.0/css/bulma.min.css" integrity="sha256-HEtF7HLJZSC3Le1HcsWbz1hDYFPZCqDhZa9QsCgVUdw=" crossorigin="anonymous" />
|
||||
|
||||
<style>
|
||||
.dz-error-mark { display:none} .dz-details {display:none}
|
||||
.dz-success-mark {display:none}
|
||||
.dz-image {display:none}
|
||||
form { width: 100% }
|
||||
|
||||
html,body {
|
||||
font-family: 'Open Sans', serif;
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
height: 100%;
|
||||
background-color: #fff;
|
||||
}
|
||||
.left-nav {
|
||||
width: 300px;
|
||||
}
|
||||
.nav.is-dark {
|
||||
background-color: #232B2D;
|
||||
color: #F6F7F7;
|
||||
}
|
||||
.nav.is-dark .nav-item a, .nav.is-dark a.nav-item {
|
||||
color: #F6F7F7;
|
||||
}
|
||||
.nav.is-dark .nav-item a.button.is-default {
|
||||
color: #F6F7F7;
|
||||
background-color: transparent;
|
||||
border-width: 2px;
|
||||
}
|
||||
.nav.menu {
|
||||
border-bottom: 1px solid #e1e1e1;
|
||||
}
|
||||
.nav.menu .nav-item .icon-btn {
|
||||
border: 3px solid #B7C6C9;
|
||||
border-radius: 90px;
|
||||
padding: 5px 7px;
|
||||
color: #B7C6C9;
|
||||
}
|
||||
.nav.menu .nav-item.is-active .icon-btn {
|
||||
color: #2EB398;
|
||||
border: 3px solid #2EB398;
|
||||
}
|
||||
.nav.menu .nav-item .icon-btn .fa {
|
||||
font-size: 20px;
|
||||
color: #B7C6C9;
|
||||
}
|
||||
.nav.menu .nav-item.is-active .icon-btn .fa {
|
||||
color: #2EB398;
|
||||
}
|
||||
.aside {
|
||||
display:block;
|
||||
background-color: #F9F9F9;
|
||||
border-right: 1px solid #DEDEDE;
|
||||
}
|
||||
.messages {
|
||||
display:block;
|
||||
background-color: #fff;
|
||||
border-right: 1px solid #DEDEDE;
|
||||
}
|
||||
.message {
|
||||
display:block;
|
||||
background-color: #fff;
|
||||
}
|
||||
.aside .compose {
|
||||
height: 95px;
|
||||
margin:0 -10px;
|
||||
padding: 25px 30px;
|
||||
}
|
||||
.aside .compose .button {
|
||||
color: #F6F7F7;
|
||||
}
|
||||
.aside .compose .button .compose {
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
}
|
||||
.aside .main {
|
||||
padding: 40px;
|
||||
color: #6F7B7E;
|
||||
}
|
||||
.aside .title {
|
||||
color: #6F7B7E;
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
.aside .main .item {
|
||||
display: block;
|
||||
padding: 10px 0;
|
||||
color: #6F7B7E;
|
||||
}
|
||||
.aside .main .item.active {
|
||||
background-color: #F1F1F1;
|
||||
margin: 0 -50px;
|
||||
padding-left: 50px;
|
||||
}
|
||||
.aside .main .item:active,.aside .main .item:hover {
|
||||
background-color: #F2F2F2;
|
||||
margin: 0 -50px;
|
||||
padding-left: 50px;
|
||||
}
|
||||
.aside .main .icon {
|
||||
font-size: 19px;
|
||||
padding-right: 30px;
|
||||
color: #A0A0A0;
|
||||
}
|
||||
.aside .main .name {
|
||||
font-size: 15px;
|
||||
color: #5D5D5D;
|
||||
font-weight: 500;
|
||||
}
|
||||
.messages {
|
||||
padding: 40px 20px;
|
||||
}
|
||||
.message {
|
||||
padding: 40px 20px;
|
||||
}
|
||||
.messages .action-buttons {
|
||||
padding: 0;
|
||||
margin-top: -20px;
|
||||
}
|
||||
.message .action-buttons {
|
||||
padding: 0;
|
||||
margin-top: -5px;
|
||||
}
|
||||
.action-buttons .control.is-grouped {
|
||||
display: inline-block;
|
||||
margin-right: 30px;
|
||||
}
|
||||
.action-buttons .control.is-grouped:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
.action-buttons .control.is-grouped .button:first-child {
|
||||
border-radius: 5px 0 0 5px;
|
||||
}
|
||||
.action-buttons .control.is-grouped .button:last-child {
|
||||
border-radius: 0 5px 5px 0;
|
||||
}
|
||||
.action-buttons .control.is-grouped .button {
|
||||
margin-right: -5px;
|
||||
border-radius: 0;
|
||||
}
|
||||
.pg {
|
||||
display: inline-block;
|
||||
top:10px;
|
||||
}
|
||||
.action-buttons .pg .title {
|
||||
display: block;
|
||||
margin-top: 0;
|
||||
padding-top: 0;
|
||||
margin-bottom: 3px;
|
||||
font-size:12px;
|
||||
color: #AAAAA;
|
||||
}
|
||||
.action-buttons .pg a{
|
||||
font-size:12px;
|
||||
color: #AAAAAA;
|
||||
text-decoration: none;
|
||||
}
|
||||
.is-grouped .button {
|
||||
background-image: linear-gradient(#F8F8F8, #F1F1F1);
|
||||
}
|
||||
.is-grouped .button .fa {
|
||||
font-size: 15px;
|
||||
color: #AAAAAA;
|
||||
}
|
||||
.inbox-messages .card {
|
||||
width: 100%;
|
||||
}
|
||||
.inbox-messages strong {
|
||||
color: #5D5D5D;
|
||||
}
|
||||
.inbox-messages .msg-check {
|
||||
padding: 0 20px;
|
||||
}
|
||||
.inbox-messages .msg-subject {
|
||||
padding: 10px 0;
|
||||
color: #5D5D5D;
|
||||
}
|
||||
.inbox-messages .msg-attachment {
|
||||
float:right;
|
||||
}
|
||||
.inbox-messages .msg-snippet {
|
||||
padding: 5px 20px 0px 5px;
|
||||
}
|
||||
.inbox-messages .msg-subject .fa {
|
||||
font-size: 14px;
|
||||
padding:3px 0;
|
||||
}
|
||||
.inbox-messages .msg-timestamp {
|
||||
float: right;
|
||||
padding: 0 20px;
|
||||
color: #5D5D5D;
|
||||
}
|
||||
.message-preview .avatar {
|
||||
display: inline-block;
|
||||
}
|
||||
.message-preview .top .address {
|
||||
display: inline-block;
|
||||
padding: 0 20px;
|
||||
}
|
||||
.avatar img {
|
||||
width: 40px;
|
||||
border-radius: 50px;
|
||||
border: 2px solid #999;
|
||||
padding: 2px;
|
||||
}
|
||||
.address .name {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.address .email {
|
||||
font-weight: bold;
|
||||
color: #B6C7D1;
|
||||
}
|
||||
.card.active {
|
||||
background-color:#F5F5F5;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app">
|
||||
<nav class="navbar has-shadow">
|
||||
<div class="container">
|
||||
<div class="navbar-brand">
|
||||
<a class="navbar-item" href="../">
|
||||
<h1>Auto-ap</h1>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<div class="has-text-centered hero is-fullheight is-vertically-centered" id="mail-app">
|
||||
<div class="is-vertically-centered">
|
||||
<h1 class="title"><i class="fa fa-spin fa-spinner"></i></h1>
|
||||
</div>
|
||||
</div>
|
||||
<footer class="footer">
|
||||
<div class="container">
|
||||
<div class="content has-text-centered">
|
||||
<p>
|
||||
<strong>Auto-AP</strong>
|
||||
by <a href="https://github.com/">Integreat</a>.
|
||||
</p>
|
||||
<p>
|
||||
<a class="icon" href="https://github.com/dansup/bulma-templates">
|
||||
<i class="fa fa-github"></i>
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js" integrity="sha256-hVVnYaiADRTO2PzUGmuLJr8BLUSjGIZsDYGmIJLv2b8=" crossorigin="anonymous"></script>
|
||||
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.0.3/vue.min.js" integrity="sha256-5CEXP4Sh+bwJYBngjYYh2TEev9kTDwcjw60jZatTHtY=" crossorigin="anonymous"></script>
|
||||
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/Faker/3.1.0/faker.min.js" integrity="sha256-QHdJObhDO++VITP6S4tMlDHRWMaUOk+s/xWIRgF/YY0=" crossorigin="anonymous"></script>
|
||||
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.15.1/moment.min.js" integrity="sha256-4PIvl58L9q7iwjT654TQJM+C/acEyoG738iL8B8nhXg=" crossorigin="anonymous"></script>
|
||||
|
||||
<script src="http://code.jquery.com/jquery-3.2.1.min.js" integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=" crossorigin="anonymous"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/dropzone@5.2.0/dist/dropzone.min.js"></script>
|
||||
|
||||
<script>
|
||||
var myDropzone = new Dropzone("#my-dropzone");
|
||||
myDropzone.on("success", function(file, a) {
|
||||
$("h2").show();
|
||||
JSON.parse(a).map(function(x) {
|
||||
/*
|
||||
$(function() {
|
||||
var lock = new Auth0Lock(
|
||||
"twbXfoLvL0tKTR6GWORoM-ss51wM1zXZ",
|
||||
"app82488100.auth0.com",
|
||||
{
|
||||
rememberLastLogin: false,
|
||||
socialButtonStyle: "big",
|
||||
oidcConformant: true,
|
||||
auth: {
|
||||
audience: "https://app82488100.auth0.com/api/v2/",
|
||||
params: {scope: 'openid email profile'},
|
||||
responseType: "token",
|
||||
redirect: true,
|
||||
redirectUrl: "http://localhost:3000",
|
||||
},
|
||||
languageDictionary: {"title":"Auto AP"},
|
||||
language: "en",
|
||||
theme: {"primaryColor":"#3A99D8"}
|
||||
} );
|
||||
|
||||
$("ul").append($("<li>").text(x));
|
||||
$(".login").click(function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
lock.show();
|
||||
});
|
||||
|
||||
lock.on("authenticated", function(result, other) {
|
||||
console.log(result.accessToken, other);
|
||||
lock.getUserInfo(result.accessToken, function(err, profile) {
|
||||
|
||||
$(".login").text(profile.nickname);
|
||||
console.log(profile);
|
||||
})
|
||||
});
|
||||
|
||||
|
||||
|
||||
var myDropzone = new Dropzone("#my-dropzone");
|
||||
myDropzone.on("success", function(file, a) {
|
||||
$("h2").show();
|
||||
$(".found-invoices").show();
|
||||
JSON.parse(a).map(function(x) {
|
||||
console.log(x);
|
||||
var tr = $("<tr>");
|
||||
tr.append($("<td>").text(x['customer-identifier']));
|
||||
tr.append($("<td>").text(x['invoice-number']));
|
||||
tr.append($("<td>").text(x['date']));
|
||||
tr.append($("<td>").text(x['total']));
|
||||
$("tbody").append(tr);
|
||||
});
|
||||
});
|
||||
});
|
||||
*/
|
||||
</script>
|
||||
</body>
|
||||
</div>
|
||||
<script src="js/compiled/app.js"></script>
|
||||
<script>auto_ap.core.init();</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -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"))
|
||||
|
||||
9
src/clj/auto_ap/server.clj
Normal file
9
src/clj/auto_ap/server.clj
Normal file
@@ -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})))
|
||||
4
src/cljs/auto_ap/config.cljs
Normal file
4
src/cljs/auto_ap/config.cljs
Normal file
@@ -0,0 +1,4 @@
|
||||
(ns auto-ap.config)
|
||||
|
||||
(def debug?
|
||||
^boolean goog.DEBUG)
|
||||
23
src/cljs/auto_ap/core.cljs
Normal file
23
src/cljs/auto_ap/core.cljs
Normal file
@@ -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))
|
||||
5
src/cljs/auto_ap/db.cljs
Normal file
5
src/cljs/auto_ap/db.cljs
Normal file
@@ -0,0 +1,5 @@
|
||||
(ns auto-ap.db)
|
||||
|
||||
(def default-db
|
||||
{:company {:name "Campbell brewery"}
|
||||
:invoices #{}})
|
||||
13
src/cljs/auto_ap/events.cljs
Normal file
13
src/cljs/auto_ap/events.cljs
Normal file
@@ -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)))
|
||||
13
src/cljs/auto_ap/subs.cljs
Normal file
13
src/cljs/auto_ap/subs.cljs
Normal file
@@ -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)))
|
||||
149
src/cljs/auto_ap/views.cljs
Normal file
149
src/cljs/auto_ap/views.cljs
Normal file
@@ -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"}]]]]]]]))
|
||||
|
||||
|
||||
|
||||
;;
|
||||
;; <nav class="navbar has-shadow">
|
||||
;; <div class="container">
|
||||
;; <div class="navbar-brand">
|
||||
;; <a class="navbar-item" href="../">
|
||||
;; <h1>Auto-ap</h1>
|
||||
;; </a>
|
||||
;;
|
||||
;; <div class="navbar-burger burger" data-target="navMenu">
|
||||
;; <span></span>
|
||||
;; <span></span>
|
||||
;; <span></span>
|
||||
;; </div>
|
||||
;; </div>
|
||||
;;
|
||||
;; <div id="navMenu" class="navbar-menu">
|
||||
;; <div class="navbar-end">
|
||||
;; <div class="navbar-item has-dropdown is-active">
|
||||
;; <a class="navbar-link login">
|
||||
;; Login
|
||||
;; </a>
|
||||
;;
|
||||
;; <div class="navbar-dropdown" style="display:none">
|
||||
;; <a class="navbar-item">
|
||||
;; Dashboard
|
||||
;; </a>
|
||||
;; <a class="navbar-item">
|
||||
;; Profile
|
||||
;; </a>
|
||||
;; <a class="navbar-item">
|
||||
;; Settings
|
||||
;; </a>
|
||||
;; <hr class="navbar-divider">
|
||||
;; <div class="navbar-item">
|
||||
;; Logout
|
||||
;; </div>
|
||||
;; </div>
|
||||
;; </div>
|
||||
;; </div>
|
||||
;; </div>
|
||||
;; </div>
|
||||
;; </nav>
|
||||
|
||||
Reference in New Issue
Block a user