stockr 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -12,6 +12,7 @@ module Stockr
12
12
  end
13
13
 
14
14
  def save
15
+ return false unless name && !name.empty?
15
16
  Store.write(name, { :qty => qty, :price => price })
16
17
  end
17
18
 
@@ -30,21 +31,34 @@ module Stockr
30
31
  end
31
32
 
32
33
  def price=(pr)
33
- @price = pr.kind_of?(Numeric) ? pr : pr.gsub(",", ".").to_f
34
+ # BigDecimal.new()
35
+ @price = pr.kind_of?(Numeric) ? pr.to_f : pr.gsub(",", ".").to_f
34
36
  end
35
37
 
36
- def self.create_or_increment(q, name, pr=0)
38
+ def price_total
39
+ price * qty
40
+ end
41
+
42
+ def to_json
43
+ "{name: '#{name}', qty: '#{qty}', price: '%.3f', total_price: '%.3f'}" % [price, price_total]
44
+ end
45
+
46
+ def self.find_or_create(q, name, pr=0, incr = false)
37
47
  part = search(name, true) || new(name)
38
- part.qty += q.to_i
48
+ incr ? part.qty += q.to_i : part.qty = q.to_i
39
49
  part.price = pr
40
50
  part.save
41
51
  part
42
52
  end
43
53
 
54
+ def self.create_or_increment(q, name, pr=0)
55
+ find_or_create(q, name, pr, true)
56
+ end
57
+
44
58
  def self.search(txt, exact = false)
45
59
  if res = Store.find(exact ? txt : "*#{txt}*")
46
60
  objs = res.map do |k, r|
47
- new(k, r["qty"])
61
+ new(k, r["qty"], r["price"])
48
62
  end
49
63
  exact ? objs[0] : objs # FIXME: better way?
50
64
  else
@@ -62,6 +76,7 @@ module Stockr
62
76
  all.select { |p| p.qty <= 0 }
63
77
  end
64
78
 
79
+
65
80
  end
66
81
 
67
82
 
@@ -17,7 +17,7 @@ module Stockr
17
17
  def find(txt)
18
18
  res = db.keys(txt)
19
19
  return nil if res.empty?
20
- res.reduce({}) { |h, r| h.merge(r => db.hgetall(r)) }
20
+ res.sort.reduce({}) { |h, r| h.merge(r => db.hgetall(r)) }
21
21
  end
22
22
 
23
23
  def write(key, values)
@@ -1,15 +1,17 @@
1
+
1
2
  require "sinatra"
3
+ unless Module.const_defined?("Stockr")
4
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__) + "/../"))
5
+ require "stockr"
6
+ end
2
7
  include Stockr
3
- # unless const_defined?("Stockr")
4
8
 
5
- # require "stockr"
6
-
7
- get '/hi' do
8
- "Hello World!"
9
- end
10
9
 
11
10
  get '/' do
12
- @parts = Part.all
11
+ parts = Part.all
12
+ @parts = parts.map(&:to_json)
13
+ @sum = parts.reduce(0) { |n, p| n += p.price_total }
14
+ p @parts
13
15
  erb <<INDEX
14
16
  <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
15
17
  <html class="cufon-active cufon-ready"><head>
@@ -17,13 +19,10 @@ get '/' do
17
19
 
18
20
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
19
21
  <title>Stockr : My Stock</title>
20
- <!--[if IE]><link rel="stylesheet" type="text/css" href="../css/tripoli.simple.ie.css" /><![endif]-->
21
- <!--[if lte IE 7]><link rel="stylesheet" type="text/css" href="../css/ie6ie7.css" /><![endif]-->
22
- <!--[if lte IE 6]><link rel="stylesheet" type="text/css" href="../css/ie6.css" /><![endif]-->
23
- <script type="text/javascript" src="knockout.js"></script>
22
+ <script type="text/javascript" src="bundle.js"></script>
24
23
 
25
- <style type="text/css">
26
- /* Tripoli overrides */
24
+ <style type="text/css">
25
+ /* CSS ************************************************************************/
27
26
  .content { font-size: 1.1em !important; }
28
27
  .content p + ul { margin-top: -0.8em; }
29
28
  .sticker .content h1 { font-size: 1.6em; margin: 0.4em 0 0.4em 0; }
@@ -34,23 +33,6 @@ get '/' do
34
33
 
35
34
  /* Basics */
36
35
  a { text-decoration: none; }
37
- code { font-family: Consolas, Monaco, "Courier New", mono-space, monospace !important; }
38
- .content .syntaxhighlighter table, .content .syntaxhighlighter td { border-width: 0; }
39
- .content .syntaxhighlighter table { margin-bottom: 0; }
40
- .syntaxhighlighter {
41
- width: 680px; overflow-x: auto; margin-bottom: 1.8em;
42
- -moz-border-radius: 0.5em; -webkit-border-radius: 0.5em; border-radius: 0.5em;
43
- }
44
- .syntaxhighlighter .line {
45
- white-space: pre !important;
46
- line-height: 1.2em;
47
- }
48
- .syntaxhighlighter code {
49
- white-space: pre !important;
50
- }
51
- .syntaxhighlighter.ie {
52
- overflow-y: hidden;
53
- }
54
36
 
55
37
  .center { text-align: center }
56
38
  .left { text-align: left }
@@ -70,19 +52,11 @@ code { font-family: Consolas, Monaco, "Courier New", mono-space, monospace !impo
70
52
  .inline { display: inline; }
71
53
  .cursor { cursor: pointer }
72
54
 
73
- ul.tickIcons li { list-style-type: none;
74
- background-image: url(../img/checkIcon.gif); background-repeat: no-repeat; background-position: 0px 6px;
75
- margin-left: -0.5em; padding-left: 2em; line-height: 2em; margin-bottom: 0.3em;
76
- }
77
-
78
- li p.smallprint { margin-top: -0.25em; line-height: 1.4em; font-size: 0.9em; margin-bottom: 0.9em; font-style: italic; color: #444; }
79
-
80
- ul.stickerList li { margin: 0.5em 0 0.9em 0; }
81
- ul.stickerList li p.smallprint { margin-top: 0.1em; }
55
+ .small { margin-top: -0.25em; line-height: 1.4em; font-size: 0.8em; margin-bottom: 0.9em; font-style: italic; color: #444; }
82
56
 
83
57
  /* Page */
84
58
  #wrapper {margin: 0 auto; width: 982px; }
85
- html { background: #d05400 url(../img/main-background.jpg) no-repeat top center; }
59
+ html { background: #d05400 no-repeat top center; }
86
60
  body { font-family: arial; font-size: 14px; }
87
61
  .sticker {
88
62
  background-color: white; padding: 1.25em 1.45em 1.25em 1.55em; margin: 0.5em 0 3em 0; -moz-border-radius: 1em; -webkit-border-radius: 1em; border-radius: 1em;
@@ -96,14 +70,10 @@ body { font-family: arial; font-size: 14px; }
96
70
  border-top-right-radius: 1em; border-top-left-radius: 1em;
97
71
  }
98
72
 
99
- .engraved {
100
- color: #350808;
101
- text-shadow: rgba(253, 204, 197, 0.4) 1px 1px 0px;
102
- }
103
-
73
+ .engraved { color: #350808; text-shadow: rgba(253, 204, 197, 0.4) 1px 1px 0px;}
104
74
  .vspace { height: 2em;}
105
75
 
106
- .liveExample { padding: 1em; background-color: #EEEEDD; border: 1px solid #CCC; max-width: 655px; }
76
+ .liveExample { padding: 1em; background-color: #EEEEDD; border: 1px solid #CCC; max-width: 98%; }
107
77
  .liveExample input { font-family: Arial; }
108
78
  .liveExample b { font-weight: bold; }
109
79
  .liveExample p { margin-top: 0.9em; margin-bottom: 0.9em; }
@@ -123,47 +93,20 @@ body { font-family: arial; font-size: 14px; }
123
93
  /* Intro */
124
94
  #introBadges li { width: 215px; float:left; text-align: center; padding: 0 0.5em 0 0.5em; color: #555; margin-bottom: 0.5em; }
125
95
 
126
- /* Homepage */
127
- #slogan {
128
- float:right; width: 17em;
129
- padding-left: 1.4em;
130
- background: url(../img/vertical-bar.png) no-repeat;
131
- font-size: 20px;
132
- margin-bottom: 0.6em;
133
- }
134
96
 
135
- .download-button {
136
- background: url(../img/download-button-bg.png);
137
- width: 173px; height: 51px;
138
- display: block;
139
- margin-top: 0.6em;
140
- }
141
- .download-button p {
142
- color: #005500;
143
- font-size: 17px;
144
- padding: 0.6em 0 0 9px;
145
- }
146
- .download-button p.smallprint {
147
- font-size: 12px;
148
- padding: 0.1em 0 0 11px;
149
- }
150
- .download-button:hover p { text-decoration: underline; }
97
+ /* Footer */
98
+ #page-footer { padding: 15px; text-align: right; }
151
99
 
100
+ .liveExample table, .liveExample td, .liveExample th { padding: 0.2em; border-width: 0; }
101
+ .liveExample td input { width: 13em; }
102
+ tr { vertical-align: top; }
103
+ .liveExample input.error { border: 1px solid red; background-color: #FDC; }
104
+ .liveExample label.error { display: block; color: Red; font-size: 0.8em; }
152
105
 
153
- .homepageExample h2 { margin: 0.75em 0 0.5em 0;}
154
- .homepageExample .liveExample { padding: 0.5em 1em 0.5em 1.3em; }
155
- .homepageExample .liveExample button { padding: 0.2em 0.6em; margin-left: 0.5em; }
156
- .homepageExample p { margin: 1.3em 0 0.8em 0; }
106
+ /* CSS ****************************************************************************/
157
107
 
158
- /* Footer */
159
- #page-footer { padding: 15px; text-align: right; }
108
+ </style>
160
109
 
161
- .liveExample table, .liveExample td, .liveExample th { padding: 0.2em; border-width: 0; }
162
- .liveExample td input { width: 13em; }
163
- tr { vertical-align: top; }
164
- .liveExample input.error { border: 1px solid red; background-color: #FDC; }
165
- .liveExample label.error { display: block; color: Red; font-size: 0.8em; }
166
- </style>
167
110
 
168
111
  </head><body>
169
112
  <div id="wrapper">
@@ -172,14 +115,14 @@ body { font-family: arial; font-size: 14px; }
172
115
  <div class="sticker">
173
116
  <div class="content">
174
117
 
175
- <script src="gridEditor_files/jquery_002.js" type="text/javascript"> </script><h2>My Stock</h2><div class="liveExample">
176
-
177
- <form action="/someServerSideHandler">
178
- <p>You have asked for <span data-bind="text: parts().length">2</span> part(s)</p>
118
+ <h2>My Stock - <%= Time.now %> </h2>
119
+ <div class="liveExample">
120
+ <form action="/up">
179
121
  <table data-bind="visible: parts().length &gt; 0">
180
122
  <thead>
181
123
  <tr>
182
- <th>Part name</th>
124
+ <th>Qty</th>
125
+ <th>Name</th>
183
126
  <th>Price</th>
184
127
  <th>
185
128
  </th></tr>
@@ -189,27 +132,27 @@ body { font-family: arial; font-size: 14px; }
189
132
 
190
133
  <button data-bind="click: addPart">Add Part</button>
191
134
  <button data-bind="enable: parts().length &gt; 0" type="submit">Submit</button>
135
+ <p>We got <span data-bind="text: parts().length">2</span> part(s). $ <%= @sum %> </p>
192
136
  </form>
193
137
 
194
- <script id="partRowTemplate" type="text/html">
195
- <tr>
196
- <td>{{ko_code ((function() { return ko.templateRewriting.applyMemoizedBindingsToNextSibling(function() { return (function() { return { value: name, uniqueName: true, '_ko_property_writers' : { value : function(__ko_value) { name = __ko_value; } } } })() }) })()) }}<input class='required' /></td>
197
- <td>{{ko_code ((function() { return ko.templateRewriting.applyMemoizedBindingsToNextSibling(function() { return (function() { return { value: price, uniqueName: true, '_ko_property_writers' : { value : function(__ko_value) { price = __ko_value; } } } })() }) })()) }}<input class='required number' /></td>
198
- <td>{{ko_code ((function() { return ko.templateRewriting.applyMemoizedBindingsToNextSibling(function() { return (function() { return { click: function() { viewModel.removePart($data) } } })() }) })()) }}<a href='#' >Delete</a></td>
199
- </tr>
200
- </script>
138
+ <script type="text/html" id="partRowTemplate">
139
+ <tr>
140
+ <td><input class="required number" data-bind="value: qty, uniqueName: true"/></td>
141
+ <td><input class="required" data-bind="value: name, uniqueName: true"/></td>
142
+ <td><input class="number" data-bind="value: price, uniqueName: true"/></td>
143
+ <td><span class="small" data-bind="text: total_price"></span></td>
144
+ <td><a href="#" data-bind="click: function() { viewModel.removePart($data) }">Delete</a></td>
145
+ </tr>
146
+ </script>
201
147
 
202
148
 
203
149
  <script type="text/javascript">
204
150
  /*<![CDATA[*/
205
151
  var viewModel = {
206
- parts: ko.observableArray([
207
- <!-- { name: "Tall Hat", price: "39.95" }, -->
208
- <!-- { name: "Long Cloak", price: "120.00" } -->
209
- ]),
152
+ parts: ko.observableArray([<%= @parts.join(',') %>]),
210
153
 
211
154
  addPart: function () {
212
- this.parts.push({ name: "", price: "" });
155
+ this.parts.push({ qty: "", name: "", price: "", total_price: "" });
213
156
  },
214
157
 
215
158
  removePart: function (part) {
@@ -217,8 +160,8 @@ body { font-family: arial; font-size: 14px; }
217
160
  },
218
161
 
219
162
  save: function (form) {
220
- alert("Could now transmit to server: " + ko.utils.stringifyJson(this.parts));
221
- // To transmit to server, write this: ko.utils.postJson($("form")[0], this.parts);
163
+ //lert("Could now transmit to server: " + ko.utils.stringifyJson(this.parts));
164
+ ko.utils.postJson($("form")[0], this.parts);
222
165
  }
223
166
  };
224
167
 
@@ -248,18 +191,7 @@ body { font-family: arial; font-size: 14px; }
248
191
 
249
192
 
250
193
  <br><br><br><br>
251
- %h1 Stockr List
252
-
253
- %table
254
- %tr
255
- %th Name
256
- %th Qty
257
- %th Price
258
- - for pr in @parts
259
- %tr
260
- %td= pr.name
261
- %td= pr.qty
262
- %td= pr.price
194
+
263
195
 
264
196
  Total:
265
197
 
@@ -270,13 +202,10 @@ get '/new' do
270
202
  haml :new
271
203
  end
272
204
 
273
- get '/knockout.js' do
274
- File.open(File.dirname(__FILE__) + "/assets/knockout.js")
205
+ get '/bundle.js' do
206
+ File.open(File.dirname(__FILE__) + "/assets/bundle.js")
275
207
  end
276
208
 
277
- get '/up' do
278
- "..."
279
- end
280
209
 
281
210
  get '/:id' do
282
211
  @part = Part.find(params[:id])
@@ -287,6 +216,20 @@ get '/:id' do
287
216
  end
288
217
  end
289
218
 
219
+
220
+ post '/up' do
221
+ params.each do |id, data|
222
+ data.gsub!(/\\|\"/, "")
223
+ # just to not require json and play
224
+ attrs = [:qty, :name, :price].map { |a| data.match(/\{?\s?(#{a})\s?:\s?(\w*)}?/)[2] }
225
+ p attrs
226
+ Part.find_or_create(*attrs)
227
+ end
228
+ "..."
229
+ redirect '/'
230
+ end
231
+
232
+
290
233
  post '/' do
291
234
  @part = Part.new(:distance => params[:distance], :minutes => params[:minutes])
292
235
  if @part.save
@@ -296,5 +239,5 @@ post '/' do
296
239
  end
297
240
  end
298
241
 
299
- Sinatra::Application.run!
242
+ # Sinatra::Application.run!
300
243
 
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
- - 0
8
7
  - 1
9
- version: 0.0.1
8
+ - 0
9
+ version: 0.1.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Marcos Piccinini
@@ -31,8 +31,21 @@ dependencies:
31
31
  prerelease: false
32
32
  version_requirements: *id001
33
33
  - !ruby/object:Gem::Dependency
34
- name: rspec
34
+ name: sinatra
35
35
  requirement: &id002 !ruby/object:Gem::Requirement
36
+ none: false
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ segments:
41
+ - 0
42
+ version: "0"
43
+ type: :development
44
+ prerelease: false
45
+ version_requirements: *id002
46
+ - !ruby/object:Gem::Dependency
47
+ name: rspec
48
+ requirement: &id003 !ruby/object:Gem::Requirement
36
49
  none: false
37
50
  requirements:
38
51
  - - ~>
@@ -44,10 +57,10 @@ dependencies:
44
57
  version: 2.1.0
45
58
  type: :development
46
59
  prerelease: false
47
- version_requirements: *id002
60
+ version_requirements: *id003
48
61
  - !ruby/object:Gem::Dependency
49
62
  name: bundler
50
- requirement: &id003 !ruby/object:Gem::Requirement
63
+ requirement: &id004 !ruby/object:Gem::Requirement
51
64
  none: false
52
65
  requirements:
53
66
  - - ~>
@@ -59,10 +72,10 @@ dependencies:
59
72
  version: 1.0.0
60
73
  type: :development
61
74
  prerelease: false
62
- version_requirements: *id003
75
+ version_requirements: *id004
63
76
  - !ruby/object:Gem::Dependency
64
77
  name: jeweler
65
- requirement: &id004 !ruby/object:Gem::Requirement
78
+ requirement: &id005 !ruby/object:Gem::Requirement
66
79
  none: false
67
80
  requirements:
68
81
  - - ~>
@@ -74,10 +87,10 @@ dependencies:
74
87
  version: 1.5.1
75
88
  type: :development
76
89
  prerelease: false
77
- version_requirements: *id004
90
+ version_requirements: *id005
78
91
  - !ruby/object:Gem::Dependency
79
92
  name: rcov
80
- requirement: &id005 !ruby/object:Gem::Requirement
93
+ requirement: &id006 !ruby/object:Gem::Requirement
81
94
  none: false
82
95
  requirements:
83
96
  - - ">="
@@ -87,10 +100,10 @@ dependencies:
87
100
  version: "0"
88
101
  type: :development
89
102
  prerelease: false
90
- version_requirements: *id005
103
+ version_requirements: *id006
91
104
  - !ruby/object:Gem::Dependency
92
105
  name: redis
93
- requirement: &id006 !ruby/object:Gem::Requirement
106
+ requirement: &id007 !ruby/object:Gem::Requirement
94
107
  none: false
95
108
  requirements:
96
109
  - - ">="
@@ -100,7 +113,7 @@ dependencies:
100
113
  version: "0"
101
114
  type: :runtime
102
115
  prerelease: false
103
- version_requirements: *id006
116
+ version_requirements: *id007
104
117
  description: Help keep track of stuff (good for electronics)
105
118
  email: x@nofxx.com
106
119
  executables:
@@ -121,7 +134,7 @@ files:
121
134
  - VERSION
122
135
  - bin/stockr
123
136
  - lib/stockr.rb
124
- - lib/stockr/assets/knockout.js
137
+ - lib/stockr/assets/bundle.js
125
138
  - lib/stockr/export.rb
126
139
  - lib/stockr/part.rb
127
140
  - lib/stockr/store.rb
@@ -143,7 +156,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
143
156
  requirements:
144
157
  - - ">="
145
158
  - !ruby/object:Gem::Version
146
- hash: 176274908678948305
159
+ hash: -709536225112595033
147
160
  segments:
148
161
  - 0
149
162
  version: "0"