stockr 0.0.1 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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"