e9_vendors 0.0.1
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.
- 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
|