a lot of progress on typeaheads, etc.

This commit is contained in:
Bryce Covert
2018-05-23 11:27:31 -07:00
parent 1a72859bd8
commit e445adec02
18 changed files with 214 additions and 85 deletions

View File

@@ -4,4 +4,4 @@
4) Permissions per location
5) List of payments
6) add payment
7) add invoice
7) add invoice - in progress

View File

@@ -92,8 +92,6 @@
:jar true
:compiler {:main auto-ap.core
:output-to "resources/public/js/compiled/app.js"
:npm-deps {:react-autocomplete "1.8.1"}
:install-deps true
:optimizations :advanced
:closure-defines {goog.DEBUG false}
:pretty-print false}}

18
resources/public/css/font.min.css vendored Normal file
View File

@@ -0,0 +1,18 @@
@font-face {
font-family: 'Open Sans';
font-style: normal;
font-weight: 300;
src: local('Open Sans Light'), local('OpenSans-Light'), url(/ttf/300.ttf) format('truetype');
}
@font-face {
font-family: 'Open Sans';
font-style: normal;
font-weight: 400;
src: local('Open Sans Regular'), local('OpenSans-Regular'), url(/ttf/400.ttf) format('truetype');
}
@font-face {
font-family: 'Open Sans';
font-style: normal;
font-weight: 700;
src: local('Open Sans Bold'), local('OpenSans-Bold'), url(/ttf/700.ttf) format('truetype');
}

File diff suppressed because one or more lines are too long

View File

@@ -4,11 +4,10 @@
<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">
<!-- 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" />
<title>Integreat</title>
<link rel="stylesheet" href="/css/fontawesome.min.css" integrity="sha256-eZrrJcwDc/3uDhsdt61sL2oOBY362qM3lon1gyExkL0=" crossorigin="anonymous" />
<link href="/css/font.min.css" rel="stylesheet">
<link rel="stylesheet" href="/css/bulma.min.css" integrity="sha256-HEtF7HLJZSC3Le1HcsWbz1hDYFPZCqDhZa9QsCgVUdw=" crossorigin="anonymous" />
<style>
form.dz { border: 2px dashed lightgray;}

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -126,15 +126,17 @@
(assoc (base-graphql args) :select [:%count.*])))))
(defn import [parsed-invoices companies vendors]
(insert-multi!
(for [{:keys [total date invoice-number customer-identifier vendor-code] :as row} parsed-invoices]
(do
(dissoc (assoc row
:company-id (:id (parse/best-match companies customer-identifier))
:vendor-id (:id (first (filter #(= (:code %) vendor-code) vendors)))
:imported false
:potential-duplicate false)
:vendor-code)))))
(->> (insert-multi!
(for [{:keys [total date invoice-number customer-identifier vendor-code] :as row} parsed-invoices]
(do
(dissoc (assoc row
:company-id (:id (parse/best-match companies customer-identifier))
:vendor-id (:id (first (filter #(= (:code %) vendor-code) vendors)))
:imported false
:potential-duplicate false)
:vendor-code))))
(map db->clj)))
(defn apply-payment [invoice-id amount]
(j/db-do-prepared (get-conn)

View File

@@ -13,6 +13,7 @@
[auto-ap.db.checks :as checks]
[auto-ap.routes.checks :as rchecks]
[auto-ap.graphql.users :as gq-users]
[auto-ap.graphql.invoices :as gq-invoices]
[auto-ap.db.reminders :as reminders]
[auto-ap.db.invoices-checks :as invoices-checks]
[auto-ap.db.utils :as utils]
@@ -141,7 +142,14 @@
:name {:type 'String}
:role {:type 'String}
:companies {:type '(list Int)}}}
}
:add_invoice
{:fields {:id {:type 'Int}
:invoice_number {:type 'String}
:date {:type 'String}
:company_id {:type 'Int}
:vendor_id {:type 'Int}
:total {:type 'Float}}}}
:mutations
{:print_checks {:type :check_result
@@ -151,7 +159,11 @@
:resolve :mutation/print-checks}
:edit_user {:type :user
:args {:edit_user {:type :edit_user}}
:resolve :mutation/edit-user}}})
:resolve :mutation/edit-user}
:add_invoice {:type :invoice
:args {:invoice {:type :add_invoice}}
:resolve :mutation/add-invoice}}})
@@ -281,10 +293,7 @@
(:company_id args)
(:bank_account_id args))))
(defn edit-user [context args value]
(Thread/sleep 1000)
(->graphql
(gq-users/edit-user (:edit_user args))))
(def schema
(-> integreat-schema
@@ -298,7 +307,8 @@
:get-user get-user
:get-user-companies get-user-companies
:mutation/print-checks print-checks
:mutation/edit-user edit-user
:mutation/edit-user gq-users/edit-user
:mutation/add-invoice gq-invoices/add-invoice
:get-vendor get-vendor})
schema/compile))

View File

@@ -0,0 +1,17 @@
(ns auto-ap.graphql.invoices
(:require [auto-ap.graphql.utils :refer [->graphql]]
[auto-ap.db.invoices :as invoices]
[auto-ap.time :refer [parse normal-date]]))
(defn add-invoice [context {{:keys [total invoice_number company_id vendor_id date] :as in} :invoice} value]
(-> (invoices/insert-multi! [{:invoice-number invoice_number
:company-id company_id
:vendor-id vendor_id
:total total
:outstanding-balance total
:status "unpaid"
:imported true
:date (parse date normal-date)}])
(first)
(->graphql)))

View File

@@ -1,8 +1,9 @@
(ns auto-ap.graphql.users
(:require [auto-ap.db.users :as users]))
(defn edit-user [user]
(users/update! user)
(users/get-by-id (:id user)))
(:require [auto-ap.db.users :as users]
[auto-ap.graphql.utils :refer [->graphql]]))
(defn edit-user [context args value]
(users/update! (:edit_user args))
(->graphql
(users/get-by-id (:edit_user args))))

View File

@@ -0,0 +1,40 @@
(ns auto-ap.graphql.utils
(:require [clojure.string :as str]
[clojure.walk :as walk]))
(defn snake->kebab [s]
(str/replace s #"_" "-"))
(defn kebab [x]
(keyword (snake->kebab (name x))))
(defn kebab->snake [s]
(str/replace s #"-" "_"))
(defn snake [x]
(keyword (kebab->snake (name x))))
(defn ->graphql [m]
(walk/postwalk
(fn [node]
(cond
(keyword? node)
(snake node)
:else
node))
m))
(defn <-graphql [m]
(walk/postwalk
(fn [node]
(cond
(keyword? node)
(kebab node)
:else
node))
m))

View File

@@ -79,11 +79,7 @@
{:status 200
:body (pr-str (invoices/get-pending (query-params "company")))
:headers {"Content-Type" "application/edn"}})
(POST "/" {:keys [edn-params]}
(invoices/insert-multi! (:rows edn-params))
{:status 200
:body (pr-str (invoices/get-all))
:headers {"Content-Type" "application/edn"}})
(POST "/approve" {:keys [query-params]}
(invoices/approve)
{:status 200

View File

@@ -1,5 +1,12 @@
(ns auto-ap.time
(:require [clj-time.core :as time]))
(:require [clj-time.core :as time]
[clj-time.format :as f]))
(defn local-now []
(time/to-time-zone (time/now) (time/time-zone-for-id "America/Los_Angeles")))
(def normal-date "MM/dd/yyyy")
(defn parse [v format]
(time/from-time-zone (f/parse (f/formatter format) v)
(time/time-zone-for-id "America/Los_Angeles")))

View File

@@ -28,7 +28,6 @@
(re-frame/reg-sub
::modal-state
(fn [db [_ id]]
(println "ID" id)
(get (:modal-state db) id)))
(re-frame/reg-sub

View File

@@ -0,0 +1,63 @@
(ns auto-ap.views.components.typeahead
(:require [reagent.core :as r]
[clojure.string :as str]))
(defn typeahead [{:keys [matches on-change field value]}]
(let [text (r/atom (or (second (first (filter #(= (first %) value) matches))) ""))
highlighted (r/atom 0)
selected (r/atom (first (first (filter #(= (first %) value) matches))))
select (fn [[id t]]
(reset! selected id)
(reset! text t)
(println [id t])
(when on-change
(on-change id)))]
(fn [{:keys [matches on-change field value]}]
(let [valid-matches (take 5 (for [[[id t :as match] i] (map vector matches (range))
:when (str/includes? (.toLowerCase t) (.toLowerCase @text))]
match))]
[:div.typeahead
(if @selected
[:div.input
[:div.control
[:div.tags.has-addons
[:span.tag @text]
[:a.tag.is-delete {:on-click (fn [] (select [nil ""]))}]]]]
[:input.input {:type "text"
:field [:vendor]
:value @text
:on-blur (fn [e]
(cond @selected
nil
(#{"" nil} @text)
nil
(seq valid-matches)
(do (select (first valid-matches))
true)
:else
(do (select [nil ""])
true)))
:on-key-up (fn [e]
(if (= 13 (.-keyCode e))
(do
(select (first valid-matches))
false)
true))
:on-change (fn [e]
(reset! highlighted (ffirst valid-matches))
(select [nil (.. e -target -value)]))}
])
(when (and (seq @text)
(not @selected)
(seq valid-matches))
[:div.typeahead-menu
[:ul
(for [[id t :as match] valid-matches]
[:li.typeahead-suggestion {:class (if (= id @highlighted)
"typeahead-highlighted")
:on-mouse-down #(do (println "MATCH" match) (select match))} t])]])]))))

View File

@@ -9,6 +9,7 @@
[auto-ap.views.pages.check :as check]
[auto-ap.views.components.invoice-table :refer [invoice-table] :as invoice-table]
[auto-ap.views.components.modal :refer [modal action-modal]]
[auto-ap.views.components.typeahead :refer [typeahead]]
[auto-ap.subs :as subs]
[auto-ap.events :as events]))
@@ -190,7 +191,29 @@
(re-frame/reg-event-fx
::create-invoice
(fn [{:keys [db]} _]
{}))
{:graphql
{:token (-> db :user)
:query-obj {:venia/operation {:operation/type :mutation
:operation/name "AddInvoice"}
:venia/queries [{:query/data [:add-invoice
{:invoice @(re-frame/subscribe [::new-invoice])}
[:id :total :outstanding-balance :date :invoice-number
[:company [:id :name]]
[:vendor [:id :name]]
]]}]}
:on-success [::invoice-created]}}))
(re-frame/reg-event-fx
::invoice-created
(fn [{:keys [db]} [_ result]]
{:dispatch [::events/modal-completed ::new-invoice]
:db (-> db
(update-in [::invoice-page :invoices]
(fn [is]
(into [(:add-invoice result)]
is)))
(dissoc ::new-invoice))}))
(defn print-checks-modal []
(let [{:keys [checked]} @(re-frame/subscribe [::invoice-page])
@@ -240,55 +263,7 @@
:max outstanding-balance
:step "0.01"}]]]]]])]]])))
(defn typeahead [{:keys [matches on-change field value]}]
(let [text (r/atom (or (second (first (filter #(= (first %) value) matches))) ""))
highlighted (r/atom 0)
selected (r/atom (first (first (filter #(= (first %) value) matches))))
select (fn [[id t]]
(reset! selected id)
(reset! text t)
(println [id t])
(when on-change
(on-change id)))]
(fn [{:keys [matches on-change field value]}]
(let [valid-matches (take 5 (for [[[id t :as match] i] (map vector matches (range))
:when (str/includes? (.toLowerCase t) (.toLowerCase @text))]
match))]
[:div.typeahead
[:input.input {:type "text"
:field [:vendor]
:value @text
:on-blur (fn [e]
(cond @selected
nil
(seq valid-matches)
(do (select (first valid-matches))
true)
:else
(do (select [nil ""])
true))
)
:on-key-up (fn [e]
(if (= 13 (.-keyCode e))
(do
(select (first valid-matches))
false)
true))
:on-change (fn [e]
(reset! highlighted (ffirst valid-matches))
(select [nil (.. e -target -value)]))}]
(when (and (seq @text)
(not @selected)
(seq valid-matches))
[:div.typeahead-menu
[:ul
(for [[id t :as match] valid-matches]
[:li.typeahead-suggestion {:class (if (= id @highlighted)
"typeahead-highlighted")
:on-mouse-down #(do (println "MATCH" match) (select match))} t])]])]))))
(defn new-invoice-modal []
(let [data @(re-frame/subscribe [::new-invoice])