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
@@ -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