cloudrider 0.3.21 → 0.3.22

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.
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
@@ -0,0 +1,16 @@
1
+ class Apiv1.UsersContactEditController extends Ember.ObjectController
2
+ redirectOut: ->
3
+ @transitionToRoute 'users.contacts.index'
4
+ notifySuccess: ->
5
+ Apiv1.Flash.register "success", "contact updated!", 5000
6
+ successfulSave: (contact) ->
7
+ @notifySuccess()
8
+ @redirectOut()
9
+ failedSave: (reason) ->
10
+ Apiv1.Flash.register "warning", "contact unsccessful: #{reason.status}", 5000
11
+ @failureReason = Apiv1.HashEx.camelize reason.responseJSON if reason.responseJSON
12
+
13
+ actions:
14
+ formSubmitted: ->
15
+ @failureReason = null
16
+ @model.save().then(_.bind @successfulSave, @).catch(_.bind @failedSave, @)
@@ -0,0 +1,21 @@
1
+ class Apiv1.UsersContactsIndexController extends Ember.ObjectController
2
+ +computed model.@each.madePrimaryAt
3
+ primaryContact: ->
4
+ @model.rejectBy("madePrimaryAt", null).firstObject
5
+
6
+ +computed model.@each.id, primaryContact.id
7
+ secondaryContacts: ->
8
+ @model.rejectBy "id", @get("primaryContact.id")
9
+
10
+ successUpdate: (contact) ->
11
+ @transitionToRoute "users.index"
12
+ @transitionToRoute "users.contacts.index"
13
+ Apiv1.Flash.register "success", "successfully made primary", 5000
14
+ failedUpdate: (reason) ->
15
+ Apiv1.Flash.register "warning", "update failed: #{reason.status}", 5000
16
+ actions:
17
+ makePrimary: (contact) ->
18
+ contact.madePrimaryAt = new Date()
19
+ contact.save().then(_.bind @successUpdate, @).catch(_.bind @failedUpdate, @)
20
+ destroyContact: (contact) ->
21
+ contact.destroyRecord().then(_.bind @successUpdate, @).catch(_.bind @failedUpdate, @)
@@ -0,0 +1,16 @@
1
+ class Apiv1.UsersContactsNewController extends Ember.ObjectController
2
+ redirectOut: ->
3
+ @transitionToRoute 'users.contacts.index'
4
+ notifySuccess: ->
5
+ Apiv1.Flash.register "success", "contact created!", 5000
6
+ successfulSave: (contact) ->
7
+ @notifySuccess()
8
+ @redirectOut()
9
+ failedSave: (reason) ->
10
+ Apiv1.Flash.register "warning", "contact unsccessful: #{reason.status}", 5000
11
+ @failureReason = Apiv1.HashEx.camelize reason.responseJSON if reason.responseJSON
12
+
13
+ actions:
14
+ formSubmitted: ->
15
+ @failureReason = null
16
+ @model.save().then(_.bind @successfulSave, @).catch(_.bind @failedSave, @)
@@ -0,0 +1,19 @@
1
+ class Apiv1.UsersIndexController extends Ember.ObjectController
2
+ +computed model.firstObject
3
+ primaryContact: ->
4
+ @model.firstObject
5
+
6
+ +computed primaryContact.name, user.companyName
7
+ companyName: -> @get("primaryContact.name") or @get("user.companyName")
8
+
9
+ +computed primaryContact.email, user.email
10
+ email: -> @get("primaryContact.email") or @get("user.email")
11
+
12
+ +computed primaryContact.phone, user.phoneNumber
13
+ phoneNumber: -> @get("primaryContact.phone") or @get("user.phoneNumber")
14
+
15
+ +computed primaryContact.address, user.address
16
+ address: -> @get("primaryContact.address") or @get("user.address")
17
+
18
+ +computed Apiv1.CurrentUserSession.data
19
+ user: -> Apiv1.HashEx.camelize get$(Apiv1, "CurrentUserSession.data")
@@ -0,0 +1,11 @@
1
+ class Apiv1.Contact extends DS.Model
2
+ name: DS.attr "string"
3
+ phone: DS.attr "string"
4
+ email: DS.attr "string"
5
+ address: DS.attr "string"
6
+ madePrimaryAt: DS.attr "string"
7
+ deletedAt: DS.attr "date"
8
+ createdAt: DS.attr "date"
9
+ updatedAt: DS.attr "date"
10
+
11
+ user: DS.belongsTo "user", async: true
@@ -0,0 +1,3 @@
1
+ class Apiv1.UsersContactRoute extends Ember.Route
2
+ model: (params) ->
3
+ @store.find "contact", params.contact_id
@@ -0,0 +1,7 @@
1
+ class Apiv1.UsersContactsIndexRoute extends Ember.Route
2
+ model: ->
3
+ @store.find "contact", user_id: @user.id
4
+
5
+ +computed Apiv1.CurrentUserSession.data
6
+ user: ->
7
+ Apiv1.HashEx.camelize get$(Apiv1, "CurrentUserSession.data")
@@ -0,0 +1,3 @@
1
+ class Apiv1.UsersContactsNewRoute extends Ember.Route
2
+ model: ->
3
+ @store.createRecord "contact", user_id: get$(Apiv1, "CurrentUserSession.id")
@@ -0,0 +1,3 @@
1
+ class Apiv1.UsersIndexRoute extends Ember.Route
2
+ model: ->
3
+ @store.find "contact", primary: true
@@ -1,11 +1,20 @@
1
1
  .row
2
- .medium-push-2.large-push-2.large-10.medium-10.small-12.columns
3
- h1.footer-title
4
- tr-span en="some company tagline"
5
- .footer-divider
6
- p.copyright <%= my_company_name %>. All Rights Reserved
7
- .medium-pull-10.large-pull-10.large-2.medium-2.small-12.columns
2
+ .small-4.medium-3.large-2.column
8
3
  select-locale class="lang-btn"
9
- button click="displayModal 'login'" class="admin-btn button secondary expand"
10
- span.capitalize
11
- tr-span en="admin"
4
+ .small-4.medium-3.large-2.column
5
+ .center-vertical
6
+ .login
7
+ if adminLoggedIn
8
+ link-to "admin.index"
9
+ tr-span en="admin"
10
+
11
+ if userLoggedIn
12
+ link-to "users.index"
13
+ tr-span en="my account"
14
+
15
+ if notLoggedIn
16
+ .pointer click="displayModal 'login'"
17
+ tr-span en="login"
18
+ .small-4.medium-6.large-8.column
19
+ .center-vertical
20
+ .copyright <%= my_company_name %>. All Rights Reserved
@@ -6,18 +6,26 @@ section#user
6
6
  tr-span en="user panel"
7
7
 
8
8
  .row.admin-nav-tabs
9
- .small-4.medium-4.large-2.columns
9
+ .small-6.medium-3.large-2.columns
10
10
  link-to "users.products.index" class="admin-nav-tab"
11
11
  span.capitalize
12
12
  tr-span en="my listings"
13
- .small-4.medium-4.large-2.columns
13
+ .small-6.medium-3.large-2.columns
14
14
  link-to "users.products.new" class="admin-nav-tab"
15
15
  span.capitalize
16
16
  tr-span en="new listing"
17
- .small-4.medium-4.large-2.columns.end
17
+ .small-6.medium-3.large-2.columns
18
18
  link-to "users.offers.index" class="admin-nav-tab"
19
19
  span.capitalize
20
20
  tr-span en="my offers"
21
+ .small-6.medium-3.large-2.columns
22
+ link-to "users.contacts.index" class="admin-nav-tab"
23
+ span.capitalize
24
+ tr-span en="my contact info"
25
+ .small-6.medium-3.large-2.columns.end
26
+ a.admin-nav-tab.pointer click="logoutUser"
27
+ span.capitalize
28
+ tr-span en="logout"
21
29
 
22
30
  .row
23
31
  .small-12.columns
@@ -0,0 +1,16 @@
1
+ .row
2
+ .small-6.medium-4.large-2.columns.end
3
+ link-to "users.contacts.index" class="button expand secondary"
4
+ i.fa.fa-chevron-left
5
+ span.capitalize.bold
6
+ tr-span en="back"
7
+ .row
8
+ .small-12.medium-10.large-8.columns.end
9
+ form-for errors=failureReason submit="formSubmitted"
10
+ == partial "users/contacts/form-core"
11
+
12
+ .button-forms
13
+ promise-button model=model class="button"
14
+ span.capitalize
15
+ i.fa.fa-check
16
+ tr-span en="submit"
@@ -0,0 +1,19 @@
1
+ .input-section attr-name="name"
2
+ label.form-label
3
+ tr-span en="company name"
4
+ Ember.TextField name="name" value=model.name placeholder="Acme Trade Co"
5
+
6
+ .input-section attr-name="email"
7
+ label.form-label
8
+ tr-span en="email"
9
+ Ember.TextField name="email" value=model.email placeholder="dog@example.co"
10
+
11
+ .input-section attr-name="phone"
12
+ label.form-label
13
+ tr-span en="phone number"
14
+ Ember.TextField name="phone" value=model.phone placeholder="(555) 123 - 1234"
15
+
16
+ .input-section attr-name="address"
17
+ label.form-label
18
+ tr-span en="company address"
19
+ Ember.TextField name="address" value=model.address placeholder="1234 Main Street, Beverly Hills, CA 90210"
@@ -0,0 +1,62 @@
1
+ .row
2
+ .small-12.medium-6.large-4.columns.end
3
+ link-to "users.contacts.new" class="button capitalize success expand"
4
+ tr-span en="add new contact"
5
+ .row
6
+ .small-12.medium-6.large-4.columns
7
+ if primaryContact
8
+ ul.pricing-table
9
+ li.title.capitalize click="makePrimary contact"
10
+ tr-span en="primary contact"
11
+ li.price= primaryContact.name
12
+ li.bullet-item
13
+ span.bold.colon
14
+ tr-span en="email"
15
+ span= primaryContact.email
16
+ li.bullet-item
17
+ span.bold.colon
18
+ tr-span en="phone"
19
+ span= primaryContact.phone
20
+ li.bullet-item
21
+ span.bold.colon
22
+ tr-span en="address"
23
+ span= primaryContact.address
24
+ li.description
25
+ span.bold.colon
26
+ tr-span en="created at"
27
+ span= primaryContact.createdAt
28
+ li.cta-button
29
+ link-to "users.contact.edit" primaryContact.id class="button capitalize"
30
+ i.fa.fa-edit
31
+ tr-span en="edit"
32
+ each contact in secondaryContacts
33
+ .small-12.medium-6.large-4.columns
34
+ ul.pricing-table
35
+ li.title.capitalize.pointer click="makePrimary contact"
36
+ tr-span en="contact"
37
+ span.parantheses
38
+ tr-span en="click to make primary"
39
+ li.price= contact.name
40
+ li.bullet-item
41
+ span.bold.colon
42
+ tr-span en="email"
43
+ span= contact.email
44
+ li.bullet-item
45
+ span.bold.colon
46
+ tr-span en="phone"
47
+ span= contact.phone
48
+ li.bullet-item
49
+ span.bold.colon
50
+ tr-span en="address"
51
+ span= contact.address
52
+ li.description
53
+ span.bold.colon
54
+ tr-span en="created at"
55
+ span= contact.createdAt
56
+ li.cta-button
57
+ link-to "users.contact.edit" contact.id class="button capitalize"
58
+ i.fa.fa-edit
59
+ tr-span en="edit"
60
+ button.button.alert.capitalize click="destroyContact contact"
61
+ i.fa.fa-times-circle
62
+ tr-span en="destroy"
@@ -0,0 +1,16 @@
1
+ .row
2
+ .small-6.medium-4.large-2.columns.end
3
+ link-to "users.index" class="button expand secondary"
4
+ i.fa.fa-chevron-left
5
+ span.capitalize.bold
6
+ tr-span en="back"
7
+ .row
8
+ .small-12.medium-10.large-8.columns.end
9
+ form-for errors=failureReason submit="formSubmitted"
10
+ == partial "users/contacts/form-core"
11
+
12
+ .button-forms
13
+ promise-button model=model class="button"
14
+ span.capitalize
15
+ i.fa.fa-check
16
+ tr-span en="submit"
@@ -1,3 +1,37 @@
1
- h4 welcome
1
+ .row
2
+ .small-12.columns
3
+ h4
4
+ span.capitalize
5
+ tr-span en="welcome"
6
+ span.prespace= companyName
7
+ .row
8
+ .small-12.columns
9
+ dl.company-info
10
+ dt
11
+ tr-span en="email"
12
+ dd
13
+ span= email
14
+ if user.userRank
15
+ dt
16
+ tr-span en="user rank"
17
+ dd
18
+ span= user.userRank
19
+ dt
20
+ tr-span en="company name"
21
+ dd
22
+ span= companyName
23
+ dt
24
+ tr-span en="phone number"
25
+ dd
26
+ span= phoneNumber
27
+ dt
28
+ tr-span en="address"
29
+ dd
30
+ span= address
31
+ dt
32
+ tr-span en="about me"
33
+ dd
34
+ span= user.aboutMe
35
+
36
+
2
37
 
3
- p.todo TODO: analytics dashboard goes here
@@ -17,8 +17,13 @@
17
17
  width: 66%;
18
18
  }
19
19
  }
20
- img.product-image {
21
- min-height: 275px;
20
+ .product-image {
21
+ width: 125px;
22
+ height: 125px;
23
+ background: {
24
+ size: cover;
25
+ position: center center;
26
+ }
22
27
  }
23
28
  .product-title {
24
29
  font-size: 2rem;
@@ -74,4 +74,7 @@
74
74
  }
75
75
  .full-width {
76
76
  width: 100%;
77
+ }
78
+ .buffer20 {
79
+ margin: 20px;
77
80
  }
@@ -0,0 +1,26 @@
1
+ class Apiv1::Contacts::CreateController < Apiv1::UsersController
2
+ def create
3
+ if _contact_creation_success?
4
+ _contact.save!
5
+ render json: _contact_hash
6
+ else
7
+ render json: _error_hash, status: :expectation_failed
8
+ end
9
+ end
10
+ private
11
+ def _contact_hash
12
+ { contact: _contact.to_ember_hash }
13
+ end
14
+ def _error_hash
15
+ { contact: _contact.errors.to_h }
16
+ end
17
+ def _contact_creation_success?
18
+ _contact.valid?
19
+ end
20
+ def _contact
21
+ @contact ||= current_user.contacts.new _contact_params
22
+ end
23
+ def _contact_params
24
+ params.require(:contact).permit(:name, :phone, :email, :address)
25
+ end
26
+ end
@@ -0,0 +1,9 @@
1
+ class Apiv1::Contacts::DestroyController < Apiv1::Contacts::UpdateController
2
+ def destroy
3
+ render json: _contact.destroy
4
+ end
5
+ private
6
+ def _contact
7
+ @contact ||= Apiv1::UserContact.find(params[:id])
8
+ end
9
+ end
@@ -0,0 +1,27 @@
1
+ class Apiv1::Contacts::IndexController < Apiv1::UsersController
2
+ def index
3
+ _search_index_process.call
4
+ end
5
+ private
6
+ def _search_index_process
7
+ _search_inputs >> (_consider_user_scope % Arrows::ID) >> _consider_primality >> _render_output
8
+ end
9
+ def _search_inputs
10
+ Arrows.lift [_user, _search_params]
11
+ end
12
+ def _consider_user_scope
13
+ Arrows.lift -> (user) { user.present? ? user.contacts : Apiv1::UserContact }
14
+ end
15
+ def _consider_primality
16
+ Arrows.lift -> (x) { x.last[:primary].present? ? x.first.is_primary.order_by_primality.limit(1) : x.first }
17
+ end
18
+ def _render_output
19
+ Arrows.lift -> (contacts) { render json: { contacts: contacts.map(&:to_ember_hash) } }
20
+ end
21
+ def _search_params
22
+ params.permit(:primary, :user_id)
23
+ end
24
+ def _user
25
+ Admin::User.find_by_id(_search_params[:user_id]) || current_user
26
+ end
27
+ end
@@ -0,0 +1,9 @@
1
+ class Apiv1::Contacts::ShowController < Apiv1::BaseController
2
+ def show
3
+ render json: { contact: _contact.to_ember_hash }
4
+ end
5
+ private
6
+ def _contact
7
+ @contact ||= Apiv1::UserContact.find params[:id]
8
+ end
9
+ end
@@ -0,0 +1,51 @@
1
+ class Apiv1::Contacts::UpdateController < Apiv1::UsersController
2
+ before_filter :_enforce_correct_user
3
+ def update
4
+ _update_process.call
5
+ end
6
+ private
7
+ def _enforce_correct_user
8
+ unless current_user.admin? || current_user.contacts.include?(_contact)
9
+ render json: { message: "This isn't your listing" }, status: 401
10
+ end
11
+ end
12
+ def _update_process
13
+ _user_inputs >> _apply_changes >> _decide_validity >> (_update_valid_data_process ^ _render_failure)
14
+ end
15
+ def _update_valid_data_process
16
+ _save_changes >> _decide_primality >> (_make_primary ^ Arrows::ID) >> _result_hashify >> _render_success
17
+ end
18
+ def _user_inputs
19
+ Arrows.lift _contact
20
+ end
21
+ def _apply_changes
22
+ Arrows.lift -> (contact) { contact.tap { |p| p.assign_attributes _contact_params } }
23
+ end
24
+ def _decide_validity
25
+ Arrows.lift -> (contact) { contact.valid? ? Arrows.good(contact) : Arrows.evil(contact) }
26
+ end
27
+ def _decide_primality
28
+ Arrows.lift -> (contact) { params[:contact][:made_primary_at].present? ? Arrows.good(contact) : Arrows.evil(contact) }
29
+ end
30
+ def _result_hashify
31
+ Arrows.lift -> (contact) { { contact: contact.to_ember_hash } }
32
+ end
33
+ def _render_success
34
+ Arrows.lift -> (result_hash) { render json: result_hash }
35
+ end
36
+ def _save_changes
37
+ Arrows.lift -> (contact) { contact.tap(&:save!) }
38
+ end
39
+ def _make_primary
40
+ Arrows.lift -> (contact) { contact.tap &:make_primary! }
41
+ end
42
+ def _render_failure
43
+ Arrows.lift -> (contact) { render json: contact.errors.to_h, status: :expectation_failed }
44
+ end
45
+ def _contact
46
+ @contact ||= Apiv1::UserContact.find params[:id]
47
+ end
48
+ def _contact_params
49
+ @contact_params ||= params.require(:contact).permit(:name, :phone, :email, :address)
50
+ end
51
+ end