statements 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +22 -0
  3. data/README.md +22 -0
  4. data/bin/statements +8 -0
  5. data/lib/html/css/main.css +115 -0
  6. data/lib/html/css/main.css.map +7 -0
  7. data/lib/html/css/main.scss +173 -0
  8. data/lib/html/index.html +94 -0
  9. data/lib/html/js/main.coffee +146 -0
  10. data/lib/html/js/main.js +174 -0
  11. data/lib/html/js/main.js.map +10 -0
  12. data/lib/html/vendor/bootstrap/css/bootstrap-theme.css +469 -0
  13. data/lib/html/vendor/bootstrap/css/bootstrap.css +6331 -0
  14. data/lib/html/vendor/bootstrap/fonts/glyphicons-halflings-regular.eot +0 -0
  15. data/lib/html/vendor/bootstrap/fonts/glyphicons-halflings-regular.svg +229 -0
  16. data/lib/html/vendor/bootstrap/fonts/glyphicons-halflings-regular.ttf +0 -0
  17. data/lib/html/vendor/bootstrap/fonts/glyphicons-halflings-regular.woff +0 -0
  18. data/lib/html/vendor/bootstrap/js/bootstrap.js +2320 -0
  19. data/lib/html/vendor/bootstrap-datepicker.js +1681 -0
  20. data/lib/html/vendor/datepicker3.css +786 -0
  21. data/lib/html/vendor/jquery-2.1.3.js +9205 -0
  22. data/lib/html/vendor/underscore.js +1416 -0
  23. data/lib/statements/cli.rb +17 -0
  24. data/lib/statements/database.rb +22 -0
  25. data/lib/statements/migrations/00_alpha.rb +43 -0
  26. data/lib/statements/models/account.rb +9 -0
  27. data/lib/statements/models/document.rb +29 -0
  28. data/lib/statements/models/transaction.rb +43 -0
  29. data/lib/statements/pdf_reader.rb +34 -0
  30. data/lib/statements/reader/common/st_george.rb +31 -0
  31. data/lib/statements/reader/st_george_credit_card.rb +53 -0
  32. data/lib/statements/reader/st_george_savings.rb +95 -0
  33. data/lib/statements/reader.rb +76 -0
  34. data/lib/statements/search.rb +48 -0
  35. data/lib/statements/server.rb +69 -0
  36. data/lib/statements/version.rb +3 -0
  37. data/lib/statements/views/footer.erb +6 -0
  38. data/lib/statements/views/row.erb +16 -0
  39. data/lib/statements/views/search.erb +25 -0
  40. data/lib/statements.rb +17 -0
  41. metadata +141 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ff2b7e3e918329fc0e03bec9e77b195c3843fda6
4
+ data.tar.gz: 42b4173c2c664d3e510d90946875b7ea0a028772
5
+ SHA512:
6
+ metadata.gz: 9e4050e7a812a5e0fa47ffd4441f9949e96f78b866b3aadf69547345bc0455c0b70671371e35e68a4b98f293be67874e2d8f956a8cbf8000cc341b01b157ed7b
7
+ data.tar.gz: 3f5c9a2c5abe973b48468fa660623c8d66de92f987c6168322cbd6ccaf41d163ee3df2a394bca7526ab7781a69b32d9f4fb91a7337ed203d0f3f24cb4543562a
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Neil E. Pearson
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,22 @@
1
+ # Statements
2
+
3
+ Builds a database of bank account transaction history by reading PDF bank statements, and provides a simple web interface for browsing data.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ $ gem install statements
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ 1. `cd` to a directory containing all your bank statements.
14
+ 2. Run `statements` and wait for new statements to be parsed.
15
+ 3. Open `http://localhost:57473` in a browser.
16
+
17
+ ## Supported banks
18
+
19
+ - St. George Credit Cards
20
+ - St. George Cash Accounts
21
+
22
+ The list is small. Want it to grow? Send a pull request!
data/bin/statements ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ lib = File.expand_path('../../lib', __FILE__)
4
+ $:.unshift lib unless $:.include? lib
5
+
6
+ require 'statements'
7
+
8
+ Statements::Cli.main Dir.pwd, ARGV
@@ -0,0 +1,115 @@
1
+ .container-fluid {
2
+ padding-top: 15px; }
3
+
4
+ #colour a:before {
5
+ content: "";
6
+ border: 1px solid transparent;
7
+ padding: 6px;
8
+ display: block;
9
+ border-radius: 15px; }
10
+ #colour a.colour-white:before {
11
+ background: white; }
12
+ #colour a.colour-red:before {
13
+ background: #a13f3e; }
14
+ #colour a.colour-yellow:before {
15
+ background: #e9d543; }
16
+ #colour a.colour-green:before {
17
+ background: #3f9d5a; }
18
+ #colour a.colour-cyan:before {
19
+ background: #99d7ff; }
20
+ #colour a.colour-blue:before {
21
+ background: #48609d; }
22
+ #colour a.colour-magenta:before {
23
+ background: #af6bd7; }
24
+
25
+ #content thead th {
26
+ padding-top: 0; }
27
+ #content td p {
28
+ margin: 0; }
29
+ #content td p.small {
30
+ color: #666; }
31
+ #content .amount,
32
+ #content tfoot tr > * {
33
+ text-align: right; }
34
+ #content .credit .amount:before {
35
+ content: "($"; }
36
+ #content .credit .amount:after {
37
+ content: ")"; }
38
+ #content .debit .amount:before,
39
+ #content tfoot td:before {
40
+ content: "$"; }
41
+ #content tr.colour-white {
42
+ background: white; }
43
+ #content tr.colour-red {
44
+ background: #ffefef; }
45
+ #content tr.colour-yellow {
46
+ background: #ffffd7; }
47
+ #content tr.colour-green {
48
+ background: #e9fce7; }
49
+ #content tr.colour-blue {
50
+ background: #ebeffd; }
51
+ #content tr.colour-cyan {
52
+ background: #e1f7f7; }
53
+ #content tr.colour-magenta {
54
+ background: #fbefff; }
55
+ #content tr > td,
56
+ #content tr > th {
57
+ background: inherit; }
58
+ #content tr.colour-white a.picker,
59
+ #content li.colour-white a {
60
+ background: white; }
61
+ #content tr.colour-red a.picker,
62
+ #content li.colour-red a {
63
+ background: #a13f3e; }
64
+ #content tr.colour-green a.picker,
65
+ #content li.colour-green a {
66
+ background: #3f9d5a; }
67
+ #content tr.colour-blue a.picker,
68
+ #content li.colour-blue a {
69
+ background: #48609d; }
70
+ #content tr.colour-cyan a.picker,
71
+ #content li.colour-cyan a {
72
+ background: #99d7ff; }
73
+ #content tr.colour-magenta a.picker,
74
+ #content li.colour-magenta a {
75
+ background: #af6bd7; }
76
+ #content tr.colour-yellow a.picker,
77
+ #content li.colour-yellow a {
78
+ background: #e9d543; }
79
+ #content td.colour {
80
+ width: 20px;
81
+ position: relative; }
82
+ #content td.colour a {
83
+ display: block;
84
+ border: 1px solid #eee;
85
+ border-radius: 10px;
86
+ width: 20px;
87
+ height: 20px; }
88
+ #content td.colour a:hover {
89
+ border-color: #ddd; }
90
+ #content td.colour ul {
91
+ list-style: none;
92
+ position: absolute;
93
+ display: block;
94
+ right: 100%;
95
+ top: 1px;
96
+ margin-bottom: 0;
97
+ width: 167px;
98
+ text-align: right;
99
+ background: white;
100
+ border: 1px solid #eee;
101
+ border-radius: 50px;
102
+ padding: 3px;
103
+ height: 28px; }
104
+ #content td.colour ul li {
105
+ display: inline-block;
106
+ margin-right: 3px; }
107
+ #content td.colour ul li:last-child {
108
+ margin-right: 0; }
109
+
110
+ footer {
111
+ font-size: .8em;
112
+ text-align: center;
113
+ padding: 20px 0; }
114
+
115
+ /*# sourceMappingURL=main.css.map */
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "mappings": "AASA,gBAAiB;EACf,WAAW,EAAE,IAAI;;AAKf,gBAAS;EACP,OAAO,EAAE,EAAE;EACX,MAAM,EAAE,qBAAqB;EAC7B,OAAO,EAAC,GAAG;EACX,OAAO,EAAE,KAAK;EACd,aAAa,EAAE,IAAI;AAErB,6BAAsB;EAAE,UAAU,EArB9B,KAAK;AAsBT,2BAAoB;EAAE,UAAU,EArB9B,OAAO;AAsBT,8BAAuB;EAAE,UAAU,EArB9B,OAAO;AAsBZ,6BAAsB;EAAE,UAAU,EArB9B,OAAO;AAsBX,4BAAqB;EAAE,UAAU,EApB9B,OAAO;AAqBV,4BAAqB;EAAE,UAAU,EAtB9B,OAAO;AAuBV,+BAAwB;EAAE,UAAU,EArB9B,OAAO;;AA2Bf,iBAAS;EACP,WAAW,EAAE,CAAC;AAGhB,aAAK;EACH,MAAM,EAAE,CAAC;EAET,mBAAQ;IACN,KAAK,EAAE,IAAI;AAIf;qBACa;EACX,UAAU,EAAE,KAAK;AAIjB,+BAAS;EAAE,OAAO,EAAE,IAAI;AACxB,8BAAQ;EAAE,OAAO,EAAE,GAAG;AAKtB;wBAAS;EAAE,OAAO,EAAE,GAAG;AAIvB,wBAAe;EACb,UAAU,EA9DkB,KAAK;AAgEnC,sBAAa;EACX,UAAU,EAhEgB,OAAO;AAkEnC,yBAAgB;EACd,UAAU,EAlEmB,OAAO;AAoEtC,wBAAe;EACb,UAAU,EApEkB,OAAO;AAsErC,uBAAc;EACZ,UAAU,EAtEiB,OAAO;AAwEpC,uBAAc;EACZ,UAAU,EAxEiB,OAAO;AA0EpC,0BAAiB;EACf,UAAU,EA1EoB,OAAO;AA4EvC;gBACK;EACH,UAAU,EAAE,OAAO;AAIvB;0BACkB;EAChB,UAAU,EA1FN,KAAK;AA6FX;wBACgB;EACd,UAAU,EA9FR,OAAO;AAiGX;0BACkB;EAChB,UAAU,EAjGN,OAAO;AAoGb;yBACiB;EACf,UAAU,EArGP,OAAO;AAwGZ;yBACiB;EACf,UAAU,EAzGP,OAAO;AA4GZ;4BACoB;EAClB,UAAU,EA7GJ,OAAO;AAgHf;2BACmB;EACjB,UAAU,EAtHL,OAAO;AAyHd,kBAAU;EACR,KAAK,EAAE,IAAI;EACX,QAAQ,EAAE,QAAQ;EAElB,oBAAE;IACA,OAAO,EAAE,KAAK;IACd,MAAM,EAAE,cAAc;IACtB,aAAa,EAAE,IAAI;IACnB,KAAK,EAAE,IAAI;IACX,MAAM,EAAE,IAAI;IAEZ,0BAAQ;MACN,YAAY,EAAE,IAAI;EAItB,qBAAG;IACD,UAAU,EAAE,IAAI;IAChB,QAAQ,EAAE,QAAQ;IAClB,OAAO,EAAE,KAAK;IACd,KAAK,EAAE,IAAI;IACX,GAAG,EAAE,GAAG;IACR,aAAa,EAAE,CAAC;IAChB,KAAK,EAAE,KAAK;IACZ,UAAU,EAAE,KAAK;IACjB,UAAU,EAAE,KAAK;IACjB,MAAM,EAAE,cAAc;IACtB,aAAa,EAAE,IAAI;IACnB,OAAO,EAAE,GAAG;IACZ,MAAM,EAAE,IAAI;IAEZ,wBAAG;MACD,OAAO,EAAE,YAAY;MACrB,YAAY,EAAE,GAAG;MAEjB,mCAAa;QACX,YAAY,EAAE,CAAC;;AAQzB,MAAO;EACL,SAAS,EAAE,IAAI;EACf,UAAU,EAAE,MAAM;EAClB,OAAO,EAAE,MAAM",
4
+ "sources": ["main.scss"],
5
+ "names": [],
6
+ "file": "main.css"
7
+ }
@@ -0,0 +1,173 @@
1
+ // Colours
2
+ $white: white; $light-white: white;
3
+ $red: #a13f3e; $light-red: #ffefef;
4
+ $yellow: #e9d543; $light-yellow: #ffffd7;
5
+ $green: #3f9d5a; $light-green: #e9fce7;
6
+ $blue: #48609d; $light-blue: #ebeffd;
7
+ $cyan: #99d7ff; $light-cyan: #e1f7f7;
8
+ $magenta: #af6bd7; $light-magenta: #fbefff;
9
+
10
+ .container-fluid {
11
+ padding-top: 15px;
12
+ }
13
+
14
+ #colour {
15
+ a {
16
+ &:before {
17
+ content: "";
18
+ border: 1px solid transparent;
19
+ padding:6px;
20
+ display: block;
21
+ border-radius: 15px;
22
+ }
23
+ &.colour-white:before { background: $white; }
24
+ &.colour-red:before { background: $red; }
25
+ &.colour-yellow:before { background: $yellow; }
26
+ &.colour-green:before { background: $green; }
27
+ &.colour-cyan:before { background: $cyan; }
28
+ &.colour-blue:before { background: $blue; }
29
+ &.colour-magenta:before { background: $magenta; }
30
+ }
31
+ }
32
+
33
+ #content {
34
+
35
+ thead th {
36
+ padding-top: 0;
37
+ }
38
+
39
+ td p {
40
+ margin: 0;
41
+
42
+ &.small {
43
+ color: #666;
44
+ }
45
+ }
46
+
47
+ .amount,
48
+ tfoot tr > * {
49
+ text-align: right;
50
+ }
51
+
52
+ .credit .amount {
53
+ &:before { content: "($"; }
54
+ &:after { content: ")"; }
55
+ }
56
+
57
+ .debit .amount,
58
+ tfoot td {
59
+ &:before { content: "$"; }
60
+ }
61
+
62
+ tr {
63
+ &.colour-white {
64
+ background: $light-white;
65
+ }
66
+ &.colour-red {
67
+ background: $light-red;
68
+ }
69
+ &.colour-yellow {
70
+ background: $light-yellow;
71
+ }
72
+ &.colour-green {
73
+ background: $light-green;
74
+ }
75
+ &.colour-blue {
76
+ background: $light-blue;
77
+ }
78
+ &.colour-cyan {
79
+ background: $light-cyan;
80
+ }
81
+ &.colour-magenta {
82
+ background: $light-magenta;
83
+ }
84
+ > td,
85
+ > th {
86
+ background: inherit;
87
+ }
88
+ }
89
+
90
+ tr.colour-white a.picker,
91
+ li.colour-white a {
92
+ background: $white;
93
+ }
94
+
95
+ tr.colour-red a.picker,
96
+ li.colour-red a {
97
+ background: $red;
98
+ }
99
+
100
+ tr.colour-green a.picker,
101
+ li.colour-green a {
102
+ background: $green;
103
+ }
104
+
105
+ tr.colour-blue a.picker,
106
+ li.colour-blue a {
107
+ background: $blue;
108
+ }
109
+
110
+ tr.colour-cyan a.picker,
111
+ li.colour-cyan a {
112
+ background: $cyan;
113
+ }
114
+
115
+ tr.colour-magenta a.picker,
116
+ li.colour-magenta a {
117
+ background: $magenta;
118
+ }
119
+
120
+ tr.colour-yellow a.picker,
121
+ li.colour-yellow a {
122
+ background: $yellow;
123
+ }
124
+
125
+ td.colour {
126
+ width: 20px;
127
+ position: relative;
128
+
129
+ a {
130
+ display: block;
131
+ border: 1px solid #eee;
132
+ border-radius: 10px;
133
+ width: 20px;
134
+ height: 20px;
135
+
136
+ &:hover {
137
+ border-color: #ddd;
138
+ }
139
+ }
140
+
141
+ ul {
142
+ list-style: none;
143
+ position: absolute;
144
+ display: block;
145
+ right: 100%;
146
+ top: 1px;
147
+ margin-bottom: 0;
148
+ width: 167px;
149
+ text-align: right;
150
+ background: white;
151
+ border: 1px solid #eee;
152
+ border-radius: 50px;
153
+ padding: 3px;
154
+ height: 28px;
155
+
156
+ li {
157
+ display: inline-block;
158
+ margin-right: 3px;
159
+
160
+ &:last-child {
161
+ margin-right: 0;
162
+ }
163
+ }
164
+ }
165
+ }
166
+
167
+ }
168
+
169
+ footer {
170
+ font-size: .8em;
171
+ text-align: center;
172
+ padding: 20px 0;
173
+ }
@@ -0,0 +1,94 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <title>Statements</title>
5
+ <meta charset="UTF-8">
6
+ <link rel="stylesheet" href="vendor/bootstrap/css/bootstrap.css"/>
7
+ <link rel="stylesheet" href="vendor/bootstrap/css/bootstrap-theme.css"/>
8
+ <link rel="stylesheet" href="vendor/datepicker3.css"/>
9
+ <link rel="stylesheet" href="css/main.css"/>
10
+ <script src="q/accounts.js"></script>
11
+ <script src="vendor/jquery-2.1.3.js"></script>
12
+ <script src="vendor/underscore.js"></script>
13
+ <script src="vendor/bootstrap/js/bootstrap.js"></script>
14
+ <script src="vendor/bootstrap-datepicker.js"></script>
15
+ <script src="js/main.js"></script>
16
+ </head>
17
+ <body>
18
+ <div class="container-fluid">
19
+ <div class="row">
20
+ <div class="col-sm-3 sidebar">
21
+ <form>
22
+ <div class="form-group">
23
+ <label for="order">Order</label>
24
+ <select id="order" name="order" class="form-control">
25
+ <option selected value="posted_at desc, document_line desc">Newest first</option>
26
+ <option value="posted_at asc, document_line desc">Oldest first</option>
27
+ <option value="description asc, posted_at asc, document_line asc">Alphabetical</option>
28
+ <option value="abs(amount) desc, description asc, posted_at asc, document_line asc">High value first</option>
29
+ <option value="abs(amount) asc, description asc, posted_at asc, document_line asc">Low value first</option>
30
+ </select>
31
+ </div>
32
+ <div class="form-group">
33
+ <label for="date-start">Period</label>
34
+ <div class="input-daterange input-group" id="date-range">
35
+ <input type="text" class="input-sm form-control" name="date-start" id="date-start" placeholder="Start"/>
36
+ <span class="input-group-addon">to</span>
37
+ <input type="text" class="input-sm form-control" name="date-end" id="date-end" placeholder="Finish"/>
38
+ </div>
39
+ </div>
40
+ <div class="form-group">
41
+ <label for="text">Search</label>
42
+ <input type="text"
43
+ class="form-control"
44
+ name="text"
45
+ id="text"
46
+ placeholder="Partial description"/>
47
+ </div>
48
+ <div class="form-group">
49
+ <label>Type</label>
50
+ <div id="type" class="btn-group btn-group-justified" role="group">
51
+ <a role="button" class="btn btn-default" data-type="credits">Credits</a>
52
+ <a role="button" class="btn btn-default active" data-type="both">Both</a>
53
+ <a role="button" class="btn btn-default" data-type="debits">Debits</a>
54
+ </div>
55
+ </div>
56
+ <div class="form-group">
57
+ <label>Colour</label>
58
+ <div id="colour" class="btn-group btn-group-justified" role="group" data-toggle="buttons">
59
+ <a role="button" class="btn btn-default active colour-white"></a>
60
+ <a role="button" class="btn btn-default active colour-red"></a>
61
+ <a role="button" class="btn btn-default active colour-yellow"></a>
62
+ <a role="button" class="btn btn-default active colour-green"></a>
63
+ <a role="button" class="btn btn-default active colour-cyan"></a>
64
+ <a role="button" class="btn btn-default active colour-blue"></a>
65
+ <a role="button" class="btn btn-default active colour-magenta"></a>
66
+ </div>
67
+ </div>
68
+ <div class="form-group">
69
+ <label>Accounts</label>
70
+ <div id="account-buttons"
71
+ class="btn-group-vertical btn-group-xs"
72
+ role="group"
73
+ style="width:100%"
74
+ data-toggle="buttons"></div>
75
+ <script>populate_accounts('#account-buttons')</script>
76
+ </div>
77
+ <div>
78
+ <div id="account-button-bulk" class="btn-group btn-group-justified" role="group">
79
+ <a role="button" class="btn btn-default" data-set="on">All</a>
80
+ <a role="button" class="btn btn-default" data-set="off">None</a>
81
+ </div>
82
+ </div>
83
+ </form>
84
+ <footer>
85
+ <p>For my Anna ❤️</p>
86
+ </footer>
87
+ </div>
88
+ <div id="content" class="col-sm-9 content">
89
+
90
+ </div>
91
+ </div>
92
+ </div>
93
+ </body>
94
+ </html>
@@ -0,0 +1,146 @@
1
+ # List of colour literals
2
+ COLOURS = 'white red yellow green cyan blue magenta'.split ' '
3
+
4
+ # Populates the list of bank accounts in the sidebar
5
+ window.populate_accounts = (id) ->
6
+ $el = $(id)
7
+ for account in accounts
8
+ a = $('<a role="button" class="btn btn-default active" />')
9
+ a.text account.name
10
+ a.append '<br/>'
11
+ a.append $('<span class="small">').text(account.number)
12
+ a.data id: account.id
13
+ $el.append a
14
+
15
+ # AJAX layer
16
+ post = (page, data) -> $.ajax
17
+ url: "q/#{page}"
18
+ method: 'post'
19
+ contentType: 'application/json; charset=UTF-8'
20
+ dataType: page.match(/[^.]+$/)[0]
21
+ data: JSON.stringify data
22
+
23
+ # Method to query the database
24
+ querying = false
25
+ query_again = false
26
+ query = ->
27
+
28
+ # Handle interrupts
29
+ if querying
30
+ query_again = true
31
+ return
32
+ querying = true
33
+ query_again = false
34
+
35
+ # Clear content
36
+ $('#content').html 'One moment...'
37
+
38
+ # Submit data
39
+ req = post 'search.html',
40
+ order: $('#order').val()
41
+ date_start: $('#date-start').val()
42
+ date_end: $('#date-end').val()
43
+ search: $('#text').val()
44
+ type: $('#type .active').data 'type'
45
+ accounts: $('#account-buttons .active').map(-> $(@).data 'id').toArray()
46
+ colours: $('#colour .active').map(-> @className.match(/colour-(\w+)/)[1]).toArray()
47
+
48
+ # On success
49
+ req.done (result) -> $('#content').html result
50
+
51
+ # On fail
52
+ req.fail -> alert 'Query failed'
53
+
54
+ # Clean up
55
+ req.always ->
56
+ querying = false
57
+ query() if query_again
58
+
59
+ # Pad querying out a bit
60
+ query = _.debounce(query, 300)
61
+
62
+ # Method to change a transaction's colour
63
+ setColour = (transactionId, colour) -> post 'colour.json',
64
+ id: transactionId
65
+ colour: colour
66
+
67
+ $ ->
68
+ # Set the date range to last financial year
69
+ months = 'Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec'.split ' '
70
+ range = end: new Date
71
+ range.end.setDate 1
72
+ range.end.setMonth range.end.getMonth() - 1 until range.end.getMonth() is 6
73
+ range.start = new Date(range.end)
74
+ range.start.setFullYear range.start.getFullYear() - 1
75
+ range.end.setDate range.end.getDate() - 1
76
+
77
+ $("#date-#{k}").val "#{i.getDate()} #{months[i.getMonth()]} #{i.getFullYear()}" for k, i of range
78
+
79
+ # Set up the date picker
80
+ $('.input-daterange').datepicker
81
+ format: "d M yyyy"
82
+ startView: 2
83
+ todayBtn: 'linked'
84
+ autoclose: true
85
+ .on 'changeDate', query
86
+
87
+ # Order
88
+ $('#order').on 'change', query
89
+
90
+ # Dates
91
+ $('date-range').on 'change', 'input', query
92
+
93
+ # Search
94
+ $('#text').on 'change keyup', query
95
+
96
+ # Colours
97
+ $('#colour').on 'click', 'a', query
98
+
99
+ # Account buttons
100
+ $accountButtons = $('#account-buttons a')
101
+ $accountButtons.on 'click', query
102
+
103
+ # Account select all/none buttons
104
+ $('#account-button-bulk').on 'click', 'a', (e) ->
105
+ set = $(e.currentTarget).data('set')
106
+ $accountButtons.toggleClass 'active', set is 'on'
107
+ query()
108
+
109
+ # Radio button behaviour for transaction types
110
+ $typeButtons = $('#type a')
111
+ $('#type').on 'click', 'a', (e) ->
112
+ return if $(e.currentTarget).hasClass 'active'
113
+ $typeButtons.each -> $(this).toggleClass 'active', this is e.currentTarget
114
+ query()
115
+
116
+ # Handler for blurring colour pickers
117
+ $picker = null
118
+ $('body').on 'click', (e) ->
119
+ target = e.currentTarget
120
+ closePicker() unless $picker and (target is $picker[0] or $picker.find(target)[0])
121
+
122
+ # Method to remove colour picker
123
+ closePicker = ->
124
+ $picker.remove() if $picker
125
+ $picker = null
126
+
127
+ # Handlers for clicks on colour pickers
128
+ $('#content').on 'click', 'td.colour a.picker', (e) ->
129
+ e.stopPropagation()
130
+ closePicker()
131
+ $tr = $(e.currentTarget).parents('tr').first()
132
+ $td = $tr.find('td.colour')
133
+ $picker = $('<ul class="colours">')
134
+ $picker.append $('<li>').addClass("colour-#{i}").append('<a href="javascript:">') for i in COLOURS
135
+ $picker.appendTo $td
136
+ $picker.on 'click', 'a', (e) ->
137
+ $li = $(e.currentTarget).parents('li').first()
138
+ colour = $li[0].className.match(/colour-(\w+)/)[1]
139
+ op = setColour $tr.data('id'), colour
140
+ op.fail -> alert 'Something went wrong. Try reloading?'
141
+ op.done -> $tr[0].className = $tr[0].className.replace /colour-\w+/, "colour-#{colour}"
142
+ closePicker()
143
+
144
+
145
+ # Do an initial query
146
+ query()