e9_vendors 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/Gemfile +4 -0
- data/README.markdown +6 -0
- data/Rakefile +1 -0
- data/app/controllers/e9_vendors/settings_controller.rb +11 -0
- data/app/controllers/e9_vendors/vendor_categories_controller.rb +36 -0
- data/app/controllers/e9_vendors/vendor_members_controller.rb +61 -0
- data/app/controllers/e9_vendors/vendor_proxies_controller.rb +38 -0
- data/app/controllers/e9_vendors/vendors_controller.rb +22 -0
- data/app/decorators/vendor_category_decorator.rb +10 -0
- data/app/decorators/vendor_member_decorator.rb +55 -0
- data/app/decorators/vendor_proxy_decorator.rb +74 -0
- data/app/decorators/vendors_decorator.rb +27 -0
- data/app/models/vendor.rb +23 -0
- data/app/models/vendor_category.rb +17 -0
- data/app/models/vendor_member.rb +21 -0
- data/app/models/vendor_proxy.rb +39 -0
- data/app/observers/vendor_member_observer.rb +17 -0
- data/app/observers/vendor_observer.rb +18 -0
- data/app/uploaders/logo_uploader.rb +14 -0
- data/app/views/e9_vendors/settings/_form.html.haml +18 -0
- data/app/views/e9_vendors/settings/show.html.haml +2 -0
- data/app/views/e9_vendors/vendor_categories/_form.html.haml +7 -0
- data/app/views/e9_vendors/vendor_categories/_table.html.haml +21 -0
- data/app/views/e9_vendors/vendor_categories/destroy.js.erb +3 -0
- data/app/views/e9_vendors/vendor_categories/edit.html.haml +2 -0
- data/app/views/e9_vendors/vendor_categories/index.html.haml +4 -0
- data/app/views/e9_vendors/vendor_categories/index.js.erb +1 -0
- data/app/views/e9_vendors/vendor_categories/new.html.haml +2 -0
- data/app/views/e9_vendors/vendor_members/_form.html.haml +49 -0
- data/app/views/e9_vendors/vendor_members/_table.html.haml +21 -0
- data/app/views/e9_vendors/vendor_members/_vendors.html.haml +24 -0
- data/app/views/e9_vendors/vendor_members/destroy.js.erb +3 -0
- data/app/views/e9_vendors/vendor_members/edit.html.haml +2 -0
- data/app/views/e9_vendors/vendor_members/index.html.haml +4 -0
- data/app/views/e9_vendors/vendor_members/index.js.erb +1 -0
- data/app/views/e9_vendors/vendor_members/new.html.haml +2 -0
- data/app/views/e9_vendors/vendor_members/widget_code.html.haml +3 -0
- data/app/views/e9_vendors/vendor_proxies/_form.html.haml +28 -0
- data/app/views/e9_vendors/vendor_proxies/_table.html.haml +16 -0
- data/app/views/e9_vendors/vendor_proxies/_table_row.html.haml +11 -0
- data/app/views/e9_vendors/vendor_proxies/destroy.js.erb +3 -0
- data/app/views/e9_vendors/vendor_proxies/edit.html.haml +2 -0
- data/app/views/e9_vendors/vendor_proxies/index.html.haml +1 -0
- data/app/views/e9_vendors/vendor_proxies/index.js.erb +1 -0
- data/app/views/e9_vendors/vendor_proxies/new.html.haml +2 -0
- data/app/views/e9_vendors/vendor_proxies/update.js.erb +7 -0
- data/app/views/e9_vendors/vendors/_form.html.haml +91 -0
- data/app/views/e9_vendors/vendors/_table.html.haml +20 -0
- data/app/views/e9_vendors/vendors/destroy.js.erb +3 -0
- data/app/views/e9_vendors/vendors/edit.html.haml +2 -0
- data/app/views/e9_vendors/vendors/index.html.haml +4 -0
- data/app/views/e9_vendors/vendors/index.js.erb +1 -0
- data/app/views/e9_vendors/vendors/new.html.haml +2 -0
- data/config/locales/vendorboon.en.yml +61 -0
- data/config/routes.rb +38 -0
- data/e9_vendors.gemspec +20 -0
- data/lib/e9_vendors.rb +24 -0
- data/lib/e9_vendors/controller.rb +18 -0
- data/lib/e9_vendors/model.rb +13 -0
- data/lib/e9_vendors/version.rb +3 -0
- data/lib/generators/e9_vendors/install_generator.rb +31 -0
- data/lib/generators/e9_vendors/templates/javascript.js +16 -0
- data/lib/generators/e9_vendors/templates/migration.rb +84 -0
- data/lib/generators/e9_vendors/templates/stylesheets/vb-widget-ie.scss +21 -0
- data/lib/generators/e9_vendors/templates/stylesheets/vb-widget.scss +151 -0
- metadata +129 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.markdown
ADDED
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'bundler/gem_tasks'
|
@@ -0,0 +1,11 @@
|
|
1
|
+
class E9Vendors::SettingsController < Admin::SettingsController
|
2
|
+
include E9Vendors::Controller
|
3
|
+
|
4
|
+
defaults :instance_name => 'settings', :resource_class => Settings
|
5
|
+
|
6
|
+
skip_before_filter :add_admin_settings_breadcrumb
|
7
|
+
|
8
|
+
def add_index_breadcrumb
|
9
|
+
add_breadcrumb! e9_t(:index_title)
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
class E9Vendors::VendorCategoriesController < Admin::ResourceController
|
2
|
+
include E9Vendors::Controller
|
3
|
+
include E9Rails::Controllers::Sortable
|
4
|
+
|
5
|
+
respond_to :html, :js
|
6
|
+
|
7
|
+
add_resource_breadcrumbs
|
8
|
+
|
9
|
+
def create
|
10
|
+
create! { collection_path }
|
11
|
+
end
|
12
|
+
|
13
|
+
def update
|
14
|
+
update! { collection_path }
|
15
|
+
end
|
16
|
+
|
17
|
+
def destroy
|
18
|
+
destroy! do |format|
|
19
|
+
format.html { redirect_to collection_path }
|
20
|
+
format.js
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
protected
|
25
|
+
|
26
|
+
##
|
27
|
+
# IR
|
28
|
+
#
|
29
|
+
def collection
|
30
|
+
get_collection_ivar || set_collection_ivar(end_of_association_chain.order(:position).all)
|
31
|
+
end
|
32
|
+
|
33
|
+
def resource
|
34
|
+
get_resource_ivar || set_resource_ivar(end_of_association_chain.find(params[:id]))
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
class E9Vendors::VendorMembersController < Admin::ResourceController
|
2
|
+
include E9Vendors::Controller
|
3
|
+
|
4
|
+
respond_to :json, :only => :show
|
5
|
+
respond_to :html, :js, :except => :show
|
6
|
+
|
7
|
+
carrierwave_column_methods :logo, :context => :admin
|
8
|
+
|
9
|
+
skip_before_filter :authenticate_user!, :filter_access_filter, :only => :show
|
10
|
+
|
11
|
+
add_resource_breadcrumbs
|
12
|
+
before_filter :add_widget_code_breadcrumb, :only => :widget_code
|
13
|
+
|
14
|
+
def show
|
15
|
+
show! do |format|
|
16
|
+
format.html { render_404 }
|
17
|
+
format.json { render :json => { :type => 'member', :resource => resource }, :callback => params[:jsonp] }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def create
|
22
|
+
create! { collection_path }
|
23
|
+
end
|
24
|
+
|
25
|
+
def update
|
26
|
+
update! { collection_path }
|
27
|
+
end
|
28
|
+
|
29
|
+
def destroy
|
30
|
+
destroy! do |format|
|
31
|
+
format.html { redirect_to collection_path }
|
32
|
+
format.js
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
protected
|
37
|
+
|
38
|
+
def resource
|
39
|
+
get_resource_ivar || set_resource_ivar(decorate end_of_association_chain.send(resource_lookup, params[:id]))
|
40
|
+
end
|
41
|
+
|
42
|
+
def resource_lookup
|
43
|
+
params[:action] == 'show' ? :find_by_md5_hash! : :find
|
44
|
+
end
|
45
|
+
|
46
|
+
def collection
|
47
|
+
get_collection_ivar || set_collection_ivar(decorate end_of_association_chain.order(:name))
|
48
|
+
end
|
49
|
+
|
50
|
+
def decorate(records)
|
51
|
+
VendorMemberDecorator.decorate(records)
|
52
|
+
end
|
53
|
+
|
54
|
+
def add_widget_code_breadcrumb
|
55
|
+
add_breadcrumb! e9_t(:widget_code_title)
|
56
|
+
end
|
57
|
+
|
58
|
+
def determine_layout
|
59
|
+
request.xhr? ? false : super
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
class E9Vendors::VendorProxiesController < Admin::ResourceController
|
2
|
+
include E9Vendors::Controller
|
3
|
+
|
4
|
+
belongs_to :vendor_member
|
5
|
+
defaults :instance_name => :vendor
|
6
|
+
|
7
|
+
add_resource_breadcrumbs
|
8
|
+
|
9
|
+
def update
|
10
|
+
update! do |format|
|
11
|
+
format.html { redirect_to collection_path }
|
12
|
+
format.js
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
protected
|
17
|
+
|
18
|
+
def determine_layout
|
19
|
+
request.xhr? ? false : super
|
20
|
+
end
|
21
|
+
|
22
|
+
def add_index_breadcrumb
|
23
|
+
add_breadcrumb parent.class.model_name.human.pluralize, polymorphic_path(parent.class)
|
24
|
+
add_breadcrumb (@index_title = e9_t(:index_title, :member => parent.name)), collection_path
|
25
|
+
end
|
26
|
+
|
27
|
+
def decorate(records)
|
28
|
+
VendorProxyDecorator.decorate(records)
|
29
|
+
end
|
30
|
+
|
31
|
+
def collection
|
32
|
+
get_collection_ivar || set_collection_ivar(decorate end_of_association_chain.joins(:vendor).order('vendors.name').all)
|
33
|
+
end
|
34
|
+
|
35
|
+
def resource
|
36
|
+
get_resource_ivar || set_resource_ivar(decorate end_of_association_chain.find(params[:id]))
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
class E9Vendors::VendorsController < Admin::ResourceController
|
2
|
+
include E9Vendors::Controller
|
3
|
+
|
4
|
+
respond_to :html, :js
|
5
|
+
|
6
|
+
carrierwave_column_methods :logo, :context => :admin
|
7
|
+
|
8
|
+
add_resource_breadcrumbs
|
9
|
+
|
10
|
+
def create; create! { collection_path } end
|
11
|
+
def update; update! { collection_path } end
|
12
|
+
def destroy; destroy! { collection_path } end
|
13
|
+
|
14
|
+
protected
|
15
|
+
|
16
|
+
##
|
17
|
+
# IR
|
18
|
+
#
|
19
|
+
def collection
|
20
|
+
@vendors ||= end_of_association_chain.order(:name).all
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
class VendorMemberDecorator < VendorsDecorator
|
2
|
+
decorates :vendor_member
|
3
|
+
|
4
|
+
def as_json(options = {})
|
5
|
+
{
|
6
|
+
:name => model.name,
|
7
|
+
:address_1 => model.address_1,
|
8
|
+
:address_2 => model.address_2,
|
9
|
+
:admin_notes => model.admin_notes,
|
10
|
+
:categories => VendorCategoryDecorator.decorate(VendorCategory.widget_visible),
|
11
|
+
:city => model.city,
|
12
|
+
:contact_email => model.contact_email,
|
13
|
+
:contact_full_name => model.contact_full_name,
|
14
|
+
:contact_phone => model.contact_phone,
|
15
|
+
:contact_title => model.contact_title,
|
16
|
+
:country => model.country,
|
17
|
+
:logo => model.logo_url,
|
18
|
+
:nickname => model.nickname,
|
19
|
+
:state => model.state,
|
20
|
+
:vendors => VendorProxyDecorator.decorate(model.vendor_proxies.widget_visible),
|
21
|
+
:website => model.website,
|
22
|
+
:widget_form_text => config_render(:vendorboon_widget_form_text),
|
23
|
+
:widget_form_title => config_render(:vendorboon_widget_form_title),
|
24
|
+
:widget_title => config_render(:vendorboon_widget_title),
|
25
|
+
:zipcode => model.zipcode
|
26
|
+
}
|
27
|
+
end
|
28
|
+
|
29
|
+
def widget_code
|
30
|
+
<<-CODE
|
31
|
+
<script type="text/javascript" src="#{script_url}"></script>
|
32
|
+
<script type="text/javascript">
|
33
|
+
try {
|
34
|
+
new VB.Widget({
|
35
|
+
code: "#{model.md5_hash}"
|
36
|
+
}).render();
|
37
|
+
} catch (e) {}
|
38
|
+
</script>
|
39
|
+
CODE
|
40
|
+
end
|
41
|
+
|
42
|
+
protected
|
43
|
+
|
44
|
+
def script_url
|
45
|
+
dir = Rails.env.development? && 'javascripts' || 'assets'
|
46
|
+
Linkable.urlify_path("/#{dir}/widget.js")
|
47
|
+
end
|
48
|
+
|
49
|
+
def liquid_context
|
50
|
+
super.merge({
|
51
|
+
'member_name' => self.name,
|
52
|
+
'member_nickname' => self.nickname
|
53
|
+
})
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
class VendorProxyDecorator < VendorsDecorator
|
2
|
+
decorates :vendor
|
3
|
+
|
4
|
+
def as_json(options={})
|
5
|
+
{
|
6
|
+
:id => self.id,
|
7
|
+
:address_1 => vendor.address_1,
|
8
|
+
:address_2 => vendor.address_2,
|
9
|
+
:admin_notes => vendor.admin_notes,
|
10
|
+
:city => vendor.city,
|
11
|
+
:categories => VendorCategoryDecorator.decorate(vendor.vendor_categories),
|
12
|
+
:contact_email => vendor.contact_email,
|
13
|
+
:contact_full_name => vendor.contact_full_name,
|
14
|
+
:contact_phone => vendor.contact_phone,
|
15
|
+
:contact_title => vendor.contact_title,
|
16
|
+
:country => vendor.country,
|
17
|
+
:discount_code => self.discount_code,
|
18
|
+
:discount_percentage => self.discount_percentage,
|
19
|
+
:discount_percentage => vendor.discount_percentage,
|
20
|
+
:display_on_widget => self.display_on_widget,
|
21
|
+
:display_on_widget_contact_form => vendor.display_on_widget_contact_form,
|
22
|
+
:landing_page => self.landing_page,
|
23
|
+
:logo => vendor.logo_url,
|
24
|
+
:long_description => liquid_render(vendor.long_description),
|
25
|
+
:member_compensation => vendor.member_compensation,
|
26
|
+
:name => vendor.name,
|
27
|
+
:nickname => vendor.nickname,
|
28
|
+
:sales_email => self.sales_email,
|
29
|
+
:sales_email => vendor.sales_email,
|
30
|
+
:sales_full_name => self.sales_full_name,
|
31
|
+
:sales_phone => self.sales_phone,
|
32
|
+
:sales_title => self.sales_title,
|
33
|
+
:short_description => liquid_render(vendor.short_description),
|
34
|
+
:state => vendor.state,
|
35
|
+
:website => vendor.website,
|
36
|
+
:zipcode => vendor.zipcode
|
37
|
+
}
|
38
|
+
end
|
39
|
+
|
40
|
+
def sales_info_array
|
41
|
+
[model.sales_full_name, model.sales_title, model.sales_phone, model.sales_email].reject(&:blank?)
|
42
|
+
end
|
43
|
+
|
44
|
+
def landing_page_url
|
45
|
+
model.landing_page =~ /^https?:/ ? model.landing_page : "http://#{model.landing_page}"
|
46
|
+
end
|
47
|
+
|
48
|
+
def label_with_default(column)
|
49
|
+
"#{model.class.human_attribute_name(column)}".tap do |retv|
|
50
|
+
if (v = model.vendor.send(column)) && v.present?
|
51
|
+
retv << ' '
|
52
|
+
retv << h.e9_t(:vendor_default, :default_value => v)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
protected
|
58
|
+
|
59
|
+
def liquid_context
|
60
|
+
super.merge({
|
61
|
+
'vendor_discount_code' => model.discount_code,
|
62
|
+
'vendor_sales_full_name' => model.sales_full_name,
|
63
|
+
'vendor_sales_title' => model.sales_title,
|
64
|
+
'vendor_sales_phone' => model.sales_phone,
|
65
|
+
'vendor_sales_email' => model.sales_email,
|
66
|
+
'vendor_landing_page' => model.landing_page,
|
67
|
+
'vendor_discount_percentage' => model.discount_percentage,
|
68
|
+
'vendor_name' => vendor.name,
|
69
|
+
'vendor_nickname' => vendor.nickname,
|
70
|
+
'member_name' => vendor_member.name,
|
71
|
+
'member_nickname' => vendor_member.nickname
|
72
|
+
})
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
class VendorsDecorator < BaseDecorator
|
2
|
+
allows :id, :role, :remove_logo!
|
3
|
+
|
4
|
+
protected
|
5
|
+
|
6
|
+
class << self
|
7
|
+
delegate :lookup_ancestors, :i18n_scope, :to => :model_class
|
8
|
+
end
|
9
|
+
|
10
|
+
# simply send it all over to the model
|
11
|
+
def method_missing(*args)
|
12
|
+
model.send(*args)
|
13
|
+
end
|
14
|
+
|
15
|
+
def liquid_render(template)
|
16
|
+
Liquid::Template.parse(template || '').render(liquid_context)
|
17
|
+
end
|
18
|
+
|
19
|
+
def config_render(key)
|
20
|
+
liquid_render(E9::Config[key])
|
21
|
+
end
|
22
|
+
|
23
|
+
def liquid_context
|
24
|
+
# from base_controller
|
25
|
+
h.liquid_env
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
class Vendor < ActiveRecord::Base
|
2
|
+
include E9Vendors::Model
|
3
|
+
|
4
|
+
has_and_belongs_to_many :vendor_categories
|
5
|
+
has_many :vendor_proxies, :dependent => :destroy
|
6
|
+
has_many :vendor_members, :through => :vendor_proxies
|
7
|
+
|
8
|
+
validates :name, :presence => true
|
9
|
+
validates :logo, :presence => true
|
10
|
+
validates :contact_email, :presence => true, :email => { :allow_blank => true }
|
11
|
+
validates :sales_email, :presence => true, :email => { :allow_blank => true }
|
12
|
+
validates :short_description, :presence => true
|
13
|
+
validates :long_description, :presence => true
|
14
|
+
validates :discount_percentage, :presence => true, :numericality => { :allow_blank => true, :greater_than_or_equal_to => 0, :less_than => 100 }
|
15
|
+
validates :member_compensation, :presence => true, :numericality => { :allow_blank => true, :greater_than_or_equal_to => 0, :less_than => 100 }
|
16
|
+
validates :landing_page, :presence => true
|
17
|
+
|
18
|
+
mount_uploader :logo, LogoUploader
|
19
|
+
|
20
|
+
def self.all_proxies
|
21
|
+
all.map {|vendor| vendor.vendor_proxies.build }
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class VendorCategory < ActiveRecord::Base
|
2
|
+
include E9Vendors::Model
|
3
|
+
|
4
|
+
has_and_belongs_to_many :vendors
|
5
|
+
|
6
|
+
validates :name, :presence => true
|
7
|
+
|
8
|
+
scope :widget_visible, lambda {
|
9
|
+
joins(:vendors => :vendor_proxies) & VendorProxy.widget_visible
|
10
|
+
}
|
11
|
+
|
12
|
+
# On updates, all members are touched, ensuring that widget JSON requests
|
13
|
+
# for the associations are pulling the most recent information
|
14
|
+
after_save :on => :update do
|
15
|
+
VendorMember.touch_all
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
class VendorMember < ActiveRecord::Base
|
2
|
+
include E9Vendors::Model
|
3
|
+
|
4
|
+
def self.add_vendor_proxy(proxy_association)
|
5
|
+
all.each {|member| member.vendor_proxies << proxy_association.build }
|
6
|
+
end
|
7
|
+
|
8
|
+
has_many :vendor_proxies, :dependent => :destroy do
|
9
|
+
def by_category
|
10
|
+
includes(:vendor => :vendor_categories)
|
11
|
+
.order('vendor_categories.position')
|
12
|
+
.group_by {|vd| vd.vendor.vendor_category.name }
|
13
|
+
end
|
14
|
+
end
|
15
|
+
has_many :vendors, :through => :vendor_proxies
|
16
|
+
|
17
|
+
mount_uploader :logo, LogoUploader
|
18
|
+
|
19
|
+
validates :name, :presence => true
|
20
|
+
validates :logo, :presence => true
|
21
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
class VendorProxy < ActiveRecord::Base
|
2
|
+
include E9Vendors::Model
|
3
|
+
|
4
|
+
belongs_to :vendor, :touch => true
|
5
|
+
belongs_to :vendor_member, :touch => true
|
6
|
+
|
7
|
+
before_validation :populate_default_discount_code, :on => :create
|
8
|
+
|
9
|
+
validates :discount_code, :presence => true, :on => :update
|
10
|
+
validates :discount_percentage, :numericality => { :greater_than_or_equal_to => 0, :less_than => 100 }
|
11
|
+
validates :sales_email, :email => { :allow_blank => true }
|
12
|
+
|
13
|
+
delegate :name, :to => :vendor, :prefix => true
|
14
|
+
|
15
|
+
scope :widget_visible, lambda { where(:display_on_widget => true) }
|
16
|
+
|
17
|
+
PROXIED_COLUMNS = %w(
|
18
|
+
discount_percentage
|
19
|
+
landing_page
|
20
|
+
sales_full_name
|
21
|
+
sales_title
|
22
|
+
sales_phone
|
23
|
+
sales_email
|
24
|
+
)
|
25
|
+
|
26
|
+
PROXIED_COLUMNS.each do |column|
|
27
|
+
class_eval %Q[def #{column}; vendor_fallback(:#{column}) end]
|
28
|
+
end
|
29
|
+
|
30
|
+
protected
|
31
|
+
|
32
|
+
def populate_default_discount_code
|
33
|
+
self.discount_code = "V-#{self.vendor.id}-#{self.vendor_member.id}"
|
34
|
+
end
|
35
|
+
|
36
|
+
def vendor_fallback(column)
|
37
|
+
read_attribute(column).presence || vendor.send(column)
|
38
|
+
end
|
39
|
+
end
|