cloudrider 0.3.21 → 0.3.22
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/generica/Gemfile +1 -1
- data/generica/Gemfile.lock +91 -51
- data/generica/app/assets/javascripts/components/product-display.js.em +4 -1
- data/generica/app/assets/javascripts/components/product-listing.js.em +4 -1
- data/generica/app/assets/javascripts/components/site-footer.js.em +12 -0
- data/generica/app/assets/javascripts/components/site-nav.js.em +15 -0
- data/generica/app/assets/javascripts/config/router.js.ls +18 -2
- data/generica/app/assets/javascripts/controllers/modals/fork_controller.js.em +4 -0
- data/generica/app/assets/javascripts/controllers/modals/login_controller.js.em +1 -4
- data/generica/app/assets/javascripts/controllers/modals/register_controller.js.em +1 -1
- data/generica/app/assets/javascripts/controllers/users/contact/edit_controller.js.em +16 -0
- data/generica/app/assets/javascripts/controllers/users/contacts/index_controller.js.em +21 -0
- data/generica/app/assets/javascripts/controllers/users/contacts/new_controller.js.em +16 -0
- data/generica/app/assets/javascripts/controllers/users/index_controller.js.em +19 -0
- data/generica/app/assets/javascripts/models/contact.js.em +11 -0
- data/generica/app/assets/javascripts/routes/users/contact_route.js.em +3 -0
- data/generica/app/assets/javascripts/routes/users/contacts/index_route.js.em +7 -0
- data/generica/app/assets/javascripts/routes/users/contacts/new_route.js.em +3 -0
- data/generica/app/assets/javascripts/routes/users/index_route.js.em +3 -0
- data/generica/app/assets/javascripts/templates/components/site-footer.emblem +18 -9
- data/generica/app/assets/javascripts/templates/users.emblem +11 -3
- data/generica/app/assets/javascripts/templates/users/contact/edit.emblem +16 -0
- data/generica/app/assets/javascripts/templates/users/contacts/_form-core.emblem +19 -0
- data/generica/app/assets/javascripts/templates/users/contacts/index.emblem +62 -0
- data/generica/app/assets/javascripts/templates/users/contacts/new.emblem +16 -0
- data/generica/app/assets/javascripts/templates/users/index.emblem +36 -2
- data/generica/app/assets/stylesheets/apiv1/components/_product-display.css.scss +7 -2
- data/generica/app/assets/stylesheets/apiv1/shared/_constants.css.scss +3 -0
- data/generica/app/controllers/apiv1/contacts/create_controller.rb +26 -0
- data/generica/app/controllers/apiv1/contacts/destroy_controller.rb +9 -0
- data/generica/app/controllers/apiv1/contacts/index_controller.rb +27 -0
- data/generica/app/controllers/apiv1/contacts/show_controller.rb +9 -0
- data/generica/app/controllers/apiv1/contacts/update_controller.rb +51 -0
- data/generica/app/controllers/apiv1/products/destroy_controller.rb +1 -1
- data/generica/app/models/admin/user.rb +20 -1
- data/generica/app/models/apiv1/user_contact.rb +51 -0
- data/generica/app/varissets/javascripts/templates/components/product-display.emblem.erb +34 -40
- data/generica/app/varissets/javascripts/templates/components/product-listing.emblem.erb +24 -16
- data/generica/app/varissets/javascripts/templates/components/site-nav.emblem.erb +12 -2
- data/generica/app/varissets/stylesheets/apiv1/components/_product-display.css.scss.erb +68 -31
- data/generica/app/varissets/stylesheets/apiv1/components/_product-listing.css.scss.erb +52 -14
- data/generica/config/routes.rb +5 -0
- data/generica/db/migrate/20141209185352_create_apiv1_user_contacts.rb +14 -0
- data/generica/spec/controllers/apiv1/contacts/update_controller_spec.rb +59 -0
- data/generica/spec/factories/admin/user_factory.rb +22 -4
- data/generica/spec/models/apiv1/user_contact_spec.rb +70 -0
- data/lib/cloudrider/version.rb +1 -1
- 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
|
@@ -1,11 +1,20 @@
|
|
1
1
|
.row
|
2
|
-
.medium-
|
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
|
-
|
10
|
-
|
11
|
-
|
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-
|
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-
|
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-
|
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
|
-
|
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
|
@@ -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,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,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
|