cloudrider 0.3.21 → 0.3.22

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/generica/Gemfile +1 -1
  3. data/generica/Gemfile.lock +91 -51
  4. data/generica/app/assets/javascripts/components/product-display.js.em +4 -1
  5. data/generica/app/assets/javascripts/components/product-listing.js.em +4 -1
  6. data/generica/app/assets/javascripts/components/site-footer.js.em +12 -0
  7. data/generica/app/assets/javascripts/components/site-nav.js.em +15 -0
  8. data/generica/app/assets/javascripts/config/router.js.ls +18 -2
  9. data/generica/app/assets/javascripts/controllers/modals/fork_controller.js.em +4 -0
  10. data/generica/app/assets/javascripts/controllers/modals/login_controller.js.em +1 -4
  11. data/generica/app/assets/javascripts/controllers/modals/register_controller.js.em +1 -1
  12. data/generica/app/assets/javascripts/controllers/users/contact/edit_controller.js.em +16 -0
  13. data/generica/app/assets/javascripts/controllers/users/contacts/index_controller.js.em +21 -0
  14. data/generica/app/assets/javascripts/controllers/users/contacts/new_controller.js.em +16 -0
  15. data/generica/app/assets/javascripts/controllers/users/index_controller.js.em +19 -0
  16. data/generica/app/assets/javascripts/models/contact.js.em +11 -0
  17. data/generica/app/assets/javascripts/routes/users/contact_route.js.em +3 -0
  18. data/generica/app/assets/javascripts/routes/users/contacts/index_route.js.em +7 -0
  19. data/generica/app/assets/javascripts/routes/users/contacts/new_route.js.em +3 -0
  20. data/generica/app/assets/javascripts/routes/users/index_route.js.em +3 -0
  21. data/generica/app/assets/javascripts/templates/components/site-footer.emblem +18 -9
  22. data/generica/app/assets/javascripts/templates/users.emblem +11 -3
  23. data/generica/app/assets/javascripts/templates/users/contact/edit.emblem +16 -0
  24. data/generica/app/assets/javascripts/templates/users/contacts/_form-core.emblem +19 -0
  25. data/generica/app/assets/javascripts/templates/users/contacts/index.emblem +62 -0
  26. data/generica/app/assets/javascripts/templates/users/contacts/new.emblem +16 -0
  27. data/generica/app/assets/javascripts/templates/users/index.emblem +36 -2
  28. data/generica/app/assets/stylesheets/apiv1/components/_product-display.css.scss +7 -2
  29. data/generica/app/assets/stylesheets/apiv1/shared/_constants.css.scss +3 -0
  30. data/generica/app/controllers/apiv1/contacts/create_controller.rb +26 -0
  31. data/generica/app/controllers/apiv1/contacts/destroy_controller.rb +9 -0
  32. data/generica/app/controllers/apiv1/contacts/index_controller.rb +27 -0
  33. data/generica/app/controllers/apiv1/contacts/show_controller.rb +9 -0
  34. data/generica/app/controllers/apiv1/contacts/update_controller.rb +51 -0
  35. data/generica/app/controllers/apiv1/products/destroy_controller.rb +1 -1
  36. data/generica/app/models/admin/user.rb +20 -1
  37. data/generica/app/models/apiv1/user_contact.rb +51 -0
  38. data/generica/app/varissets/javascripts/templates/components/product-display.emblem.erb +34 -40
  39. data/generica/app/varissets/javascripts/templates/components/product-listing.emblem.erb +24 -16
  40. data/generica/app/varissets/javascripts/templates/components/site-nav.emblem.erb +12 -2
  41. data/generica/app/varissets/stylesheets/apiv1/components/_product-display.css.scss.erb +68 -31
  42. data/generica/app/varissets/stylesheets/apiv1/components/_product-listing.css.scss.erb +52 -14
  43. data/generica/config/routes.rb +5 -0
  44. data/generica/db/migrate/20141209185352_create_apiv1_user_contacts.rb +14 -0
  45. data/generica/spec/controllers/apiv1/contacts/update_controller_spec.rb +59 -0
  46. data/generica/spec/factories/admin/user_factory.rb +22 -4
  47. data/generica/spec/models/apiv1/user_contact_spec.rb +70 -0
  48. data/lib/cloudrider/version.rb +1 -1
  49. metadata +25 -2
@@ -1,4 +1,4 @@
1
- class Apiv1::Products::DestroyController < Admin::BaseController
1
+ class Apiv1::Products::DestroyController < Apiv1::UsersController
2
2
  before_filter :_ensure_product_ownership
3
3
  def destroy
4
4
  render json: { product: _product.destroy }
@@ -35,6 +35,20 @@ class Admin::User < ActiveRecord::Base
35
35
  class_name: 'Apiv1::Product',
36
36
  through: :product_relationships
37
37
 
38
+ has_many :raw_contacts,
39
+ class_name: 'Apiv1::UserContact',
40
+ foreign_key: 'user_id'
41
+
42
+ has_many :contacts,
43
+ -> { order_by_primality },
44
+ class_name: 'Apiv1::UserContact',
45
+ foreign_key: 'user_id'
46
+
47
+ has_one :primary_contact,
48
+ -> { is_primary.order_by_primality },
49
+ class_name: 'Apiv1::UserContact',
50
+ foreign_key: 'user_id'
51
+
38
52
  has_many :offers,
39
53
  -> { order "#{Apiv1::OfferMessage.table_name}.created_at desc" },
40
54
  through: :products,
@@ -49,7 +63,7 @@ class Admin::User < ActiveRecord::Base
49
63
  phone_number: phone_number,
50
64
  address: address,
51
65
  about_me: about_me
52
- }
66
+ }.merge _primary_contact_hash
53
67
  end
54
68
 
55
69
  def admin?
@@ -63,4 +77,9 @@ class Admin::User < ActiveRecord::Base
63
77
  def owns?(product)
64
78
  product_relationships.exists?(product_id: product.id)
65
79
  end
80
+
81
+ private
82
+ def _primary_contact_hash
83
+ primary_contact.try(:to_user_hash) || {}
84
+ end
66
85
  end
@@ -0,0 +1,51 @@
1
+ # == Schema Information
2
+ #
3
+ # Table name: apiv1_user_contacts
4
+ #
5
+ # id :integer not null, primary key
6
+ # user_id :integer
7
+ # name :string(255)
8
+ # phone :string(255)
9
+ # email :string(255)
10
+ # address :string(255)
11
+ # status :string(255)
12
+ # deleted_at :datetime
13
+ # created_at :datetime
14
+ # updated_at :datetime
15
+ #
16
+
17
+ class Apiv1::UserContact < ActiveRecord::Base
18
+ KnownStatuses = ['primary']
19
+ acts_as_paranoid
20
+ belongs_to :user,
21
+ class_name: 'Admin::User'
22
+
23
+ scope :is_primary,
24
+ -> { where "#{self.table_name}.status" => 'primary' }
25
+
26
+ validates :user,
27
+ presence: true
28
+
29
+ def make_primary!
30
+ return if user.primary_contact == self
31
+ user.primary_contact.try :demote_to_secondary!
32
+ update status: 'primary'
33
+ end
34
+
35
+ def demote_to_secondary!
36
+ update status: nil
37
+ end
38
+
39
+ def to_user_hash
40
+ {
41
+ email: email,
42
+ company_name: name,
43
+ phone_number: phone,
44
+ address: address
45
+ }
46
+ end
47
+
48
+ def to_ember_hash
49
+ attributes
50
+ end
51
+ end
@@ -3,7 +3,7 @@
3
3
  if product
4
4
  .media-object
5
5
  link-to "products.product.show" product.id
6
- img.product-image src=product.pictures.firstObject.picUrl
6
+ .product-image style=productImageStyle
7
7
  .media-texts
8
8
  link-to "products.product.show" product.id class="product-title"
9
9
  tr-span en=product.material
@@ -27,48 +27,41 @@ else
27
27
 
28
28
  <% when :media_one %>
29
29
  if product
30
- .media-object
31
- link-to "products.product.show" product.id
32
- img.product-image src=product.pictures.firstObject.picUrl
33
- .media-texts
34
- h2.product-title
35
- link-to "products.product.show" product.id
30
+ link-to "products.product.show" product.id class="flex-start"
31
+ .media-object
32
+ .product-image style=productImageStyle
33
+ .media-texts
34
+ .product-title
35
+ i.fa.fa-star
36
36
  tr-span en=product.material
37
37
  if product.sku
38
38
  span.predash= product.sku
39
- if product.taxons
40
- .taxon-tags
41
- each taxon in product.taxons
42
- span.tag= taxon.taxonName
43
- if product.others
44
- p.product-summary
45
- tr-span en=product.others
46
- if product.attachments
47
- p.related-files
48
- each attachment in product.attachments
49
- a href=attachment.fileUrl
50
- span.spacebar= attachment.fileName
51
- dl.product-specs
52
- if product.amount
53
- dt.upcase
54
- tr-span en="quantity"
55
- dd
56
- span.spacebar= product.amount
57
- if product.price
58
- dt.upcase
59
- tr-span en="price"
60
- dd
61
- span= product.price
62
- if product.place
63
- dt.upcase
64
- tr-span en="location"
65
- dd
66
- span= product.place
67
- if product.quality
68
- dt.upcase
69
- tr-span en="quality"
70
- dd
71
- span= product.quality
39
+
40
+ .product-specs
41
+ if product.amount
42
+ .line
43
+ span.upcase.colon
44
+ tr-span en="quantity"
45
+ span.spec.spacebar= product.amount
46
+ if product.price
47
+ .line
48
+ span.upcase.colon
49
+ tr-span en="price"
50
+ span.spec.spacebar= product.price
51
+ if product.place
52
+ .line
53
+ span.upcase.colon
54
+ tr-span en="origin"
55
+ span.spec.spacebar= product.place
56
+ if product.quality
57
+ .line
58
+ span.upcase.colon
59
+ tr-span en="quality"
60
+ span.spec.spacebar= product.quality
61
+ .line
62
+ span.upcase.colon
63
+ tr-span en="creation date"
64
+ span.spec.spacebar= product.createdAt
72
65
  else
73
66
  .media-object.align-right
74
67
  i.fa.fa-circle-o.fa-4x
@@ -77,5 +70,6 @@ else
77
70
  tr-span en="no results"
78
71
  p.product-summary
79
72
  tr-span en="or perhaps there are no products to load yet"
73
+
80
74
  <% when :square_tiles %>
81
75
  <% end %>
@@ -3,29 +3,36 @@
3
3
  if product
4
4
  link-to "products.product.show" product.id class="product-header"
5
5
  .media-object
6
- img.product-image.th src=product.pictures.firstObject.thumbUrl
6
+ .product-image.th style=productImageStyle
7
7
  .media-texts
8
8
  .big-title
9
9
  tr-span en=product.material
10
- if product.quality
11
- span.predash
12
- tr-span en=product.quality
13
- span.right
14
- if product.hasShowOrder
15
- span #
16
- span.spacebar= product.showcaseOrder
17
-
18
- .smaller-details
10
+ if product.sku
11
+ span.predash= product.sku
12
+ .dateline= product.createdAt
13
+ p.smaller-details
19
14
  if product.price
20
15
  span= product.price
21
16
  if product.place
22
- span @
17
+ span.decent-prespace @
23
18
  tr-span en=product.place
24
-
25
- if product.taxons
26
- .taxon-tags
27
- each taxon in product.taxons
28
- span.tag= taxon.taxonName
19
+ if product.amount
20
+ span.upcase.colon.decent-prespace
21
+ tr-span en="quantity"
22
+ span.spec.spacebar= product.amount
23
+ if product.price
24
+ span.upcase.colon.decent-prespace
25
+ tr-span en="price"
26
+ span.spec.spacebar= product.price
27
+ if product.place
28
+ span.upcase.colon.decent-prespace
29
+ tr-span en="origin"
30
+ span.spec.spacebar= product.place
31
+ if product.quality
32
+ span.upcase.colon.decent-prespace
33
+ tr-span en="quality"
34
+ span.spec.spacebar= product.quality
35
+
29
36
  else
30
37
  .product-header
31
38
  .media-object
@@ -35,4 +42,5 @@ else
35
42
  tr-span en="no results"
36
43
  .product-summary
37
44
  tr-span en="or perhaps there are no products to load yet"
45
+
38
46
  <% end %>
@@ -5,8 +5,18 @@
5
5
  .space-between
6
6
  link-to "index" class="button-like"
7
7
  span <%= my_company_name %>
8
- a.pointer.button-like click="displayModal 'login'"
9
- tr-span en="my account"
8
+ if adminLoggedIn
9
+ link-to "admin.index"
10
+ tr-span en="admin"
11
+
12
+ if userLoggedIn
13
+ link-to "users.index" class="button-like"
14
+ tr-span en="my account"
15
+
16
+ if notLoggedIn
17
+ a.pointer.button-like click="displayModal 'login'"
18
+ tr-span en="login or register"
19
+
10
20
  <% when :left %>
11
21
  .nav-button
12
22
  link-to "index" (query-params anchor="") class="side-nav"
@@ -70,57 +70,94 @@ $material-orange: #FF9800;
70
70
  }
71
71
  <% when :media_one %>
72
72
  .product-display {
73
- .media-object {
74
- padding-left: 15px;
73
+ background: {
74
+ color: #eeeeee;
75
+ }
76
+ &:nth-child(even) {
77
+ background: {
78
+ color: #e5e5e5;
79
+ }
80
+ }
81
+ &:hover {
82
+ background: {
83
+ color: #f1f1f1;
84
+ }
85
+ }
86
+ .flex-start {
87
+ @include display-flex;
75
88
  @media #{$small-only} {
76
- width: 100%;
89
+ @include flex-direction(column);
90
+ @include justify-content(flex-start);
91
+ @include align-items(center);
77
92
  }
78
93
  @media #{$medium-up} {
79
- width: 33%;
94
+ @include flex-direction(row);
95
+ @include justify-content(flex-start);
80
96
  }
81
97
  }
82
98
  .media-texts {
83
- padding-left: 15px;
84
99
  @media #{$small-only} {
85
100
  width: 100%;
101
+ @include order(-1);
86
102
  }
87
- @media #{$medium-up} {
88
- width: 66%;
103
+ @media #{$medium-only} {
104
+ width: 100%;
89
105
  }
90
106
  }
91
- img.product-image {
92
- min-height: 275px;
107
+ .product-image {
108
+ @media #{$small-only} {
109
+ width: 175px;
110
+ height: 175px;
111
+ }
112
+ @media #{$medium-only} {
113
+ width: 75px;
114
+ height: 75px;
115
+ }
116
+ @media #{$large-up} {
117
+ width: 125px;
118
+ height: 125px;
119
+ }
120
+ background: {
121
+ size: cover;
122
+ position: center center;
123
+ }
93
124
  }
94
125
  .product-title {
95
- font-size: 1.25rem;
96
- text-transform: capitalize;
126
+ font-size: 1.15rem;
127
+ font-weight: bold;
128
+ }
129
+ .product-summary {
130
+ font-size: 0.85rem;
131
+ margin-bottom: 0.5rem;
132
+ color: #333;
133
+ }
134
+ .media-texts {
135
+ margin-left: 1rem;
136
+ padding-bottom: 1rem;
137
+ padding-top: 1rem;
138
+ }
139
+ .spec {
140
+ margin-right: 1rem;
97
141
  }
98
- dl.product-specs {
99
- font-size: 0.75rem;
142
+ .product-specs {
143
+ font-size: 0.8rem;
144
+ color: #333;
100
145
  }
101
146
  .taxon-tags {
102
- padding-bottom: 15px;
147
+ margin-top: 5px;
148
+ padding-top: 5px;
149
+ padding-bottom: 5px;
103
150
  }
104
151
  .tag {
105
- @include transition-property(background-color);
106
- @include transition-duration(300ms);
107
- @include transition-timing-function(ease-out);
108
- background: {
109
- color: darken(red, 25%);
110
- }
111
- &:hover {
112
- background-color: darken(red, 15%);
113
- }
114
- &:before {
152
+ margin-left: 5px;
153
+ margin-right: 10px;
154
+ &::before {
115
155
  content: "+";
116
156
  }
117
- font-size: 1rem;
118
- color: #ddd;
119
- padding-left: 5px;
120
- padding-right: 10px;
121
- padding-top: 5px;
122
- padding-bottom: 5px;
123
- margin-right: 10px;
157
+ color: #666;
158
+ font-weight: bold;
124
159
  }
125
160
  }
161
+
162
+
126
163
  <% end %>
@@ -5,37 +5,72 @@
5
5
  @include transition-duration(300ms);
6
6
  @include transition-timing-function(ease-out);
7
7
  background: {
8
- color: #ccc;
8
+ color: #eeeeee;
9
9
  }
10
10
  &:hover {
11
11
  background: {
12
- color: #ddd;
12
+ color: #f1f1f1;
13
13
  }
14
14
  }
15
+
15
16
  .product-image {
16
- width: 100px;
17
- max-height: 200px;
17
+ @media #{$small-only} {
18
+ width: 175px;
19
+ height: 175px;
20
+ }
21
+ @media #{$medium-up} {
22
+ width: 100px;
23
+ height: 100px;
24
+ }
25
+ @media #{$large-up} {
26
+ width: 125px;
27
+ height: 125px;
28
+ }
29
+ background: {
30
+ size: cover;
31
+ position: center center;
32
+ }
18
33
  }
19
34
  .media-texts {
20
35
  font-size: 1.45rem;
21
36
  width: 100%;
37
+ @media #{$small-only} {
38
+ @include order(-1);
39
+ }
40
+ }
41
+ .big-title {
42
+ padding-top: 10px;
43
+ padding-bottom: 10px;
44
+ }
45
+ .dateline {
46
+ font-size: 0.9rem;
47
+ font-weight: bold;
48
+ margin-bottom: 10px;
49
+ color: #777;
22
50
  }
23
51
  .smaller-details {
24
52
  font-size: 0.8rem;
53
+ color: #444;
25
54
  }
26
55
  .media-object {
27
56
  margin-right: 15px;
28
57
  }
29
58
  .product-header {
30
59
  @include display-flex;
31
- @include flex-direction(row);
32
- @include justify-content(flex-start);
33
60
  @include align-items(center);
61
+ @media #{$small-only} {
62
+ @include flex-direction(column);
63
+ @include justify-content(flex-start);
64
+ }
65
+ @media #{$medium-up} {
66
+ @include flex-direction(row);
67
+ @include justify-content(flex-start);
68
+ }
34
69
  border-bottom: 1px solid #bbb;
35
70
  }
36
71
  .taxon-tags {
37
- margin-top: 5px;
38
- margin-bottom: 5px;
72
+ margin-top: 2.5px;
73
+ margin-bottom: 2.5px;
39
74
  }
40
75
  .tag {
41
76
  @include transition-property(background-color);
@@ -50,13 +85,16 @@
50
85
  &:before {
51
86
  content: "+";
52
87
  }
53
- font-size: 1.15rem;
88
+ font-size: 0.8rem;
54
89
  color: #ddd;
55
- padding-left: 5px;
56
- padding-right: 10px;
57
- padding-top: 5px;
58
- padding-bottom: 5px;
59
- margin-right: 10px;
90
+ padding-left: 2.5px;
91
+ padding-right: 5px;
92
+ padding-top: 2.5px;
93
+ padding-bottom: 2.5px;
94
+ margin-right: 5px;
95
+ }
96
+ .decent-prespace {
97
+ padding-left: 1.2rem;
60
98
  }
61
99
  <% end %>
62
100
  }