tienda 1.1.2 → 2.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/assets/javascripts/tienda/application.coffee +114 -84
- data/app/assets/javascripts/tienda/custom-scripts.js +182 -0
- data/app/assets/javascripts/tienda/custom.js +200 -0
- data/app/assets/javascripts/tienda/jquery.metisMenu.js +45 -0
- data/app/assets/javascripts/tienda/morris.js +1913 -0
- data/app/assets/javascripts/tienda/raphael-2.1.0.min.js +10 -0
- data/app/assets/stylesheets/tienda/application.scss +2 -577
- data/app/assets/stylesheets/tienda/custom-styles.scss +518 -0
- data/app/assets/stylesheets/tienda/morris-0.4.3.min.css +2 -0
- data/app/controllers/tienda/dashboard_controller.rb +11 -1
- data/app/controllers/tienda/products_controller.rb +7 -3
- data/app/controllers/tienda/sessions_controller.rb +1 -1
- data/app/controllers/tienda/stock_level_adjustments_controller.rb +1 -5
- data/app/helpers/tienda/application_helper.rb +10 -4
- data/app/models/tienda/country.rb +3 -5
- data/app/models/tienda/delivery_service.rb +5 -7
- data/app/models/tienda/order/actions.rb +3 -3
- data/app/models/tienda/order/delivery.rb +1 -1
- data/app/models/tienda/order.rb +8 -8
- data/app/models/tienda/order_item.rb +11 -11
- data/app/models/tienda/product.rb +38 -54
- data/app/models/tienda/stock_level_adjustment.rb +9 -7
- data/app/models/tienda/tax_rate.rb +5 -7
- data/app/models/tienda/user.rb +4 -4
- data/app/validators/permalink_validator.rb +1 -1
- data/app/views/layouts/tienda/application.html.haml +29 -22
- data/app/views/layouts/tienda/sub.html.haml +44 -6
- data/app/views/tienda/application/_navbar.html.haml +164 -0
- data/app/views/tienda/application/_sidebar.html.haml +6 -0
- data/app/views/tienda/countries/_form.html.haml +40 -34
- data/app/views/tienda/countries/edit.html.haml +12 -3
- data/app/views/tienda/countries/index.html.haml +31 -21
- data/app/views/tienda/countries/new.html.haml +11 -3
- data/app/views/tienda/dashboard/home.html.haml +156 -0
- data/app/views/tienda/delivery_service_prices/_form.html.haml +53 -39
- data/app/views/tienda/delivery_service_prices/edit.html.haml +12 -3
- data/app/views/tienda/delivery_service_prices/index.html.haml +28 -19
- data/app/views/tienda/delivery_service_prices/new.html.haml +12 -3
- data/app/views/tienda/delivery_services/_form.html.haml +48 -35
- data/app/views/tienda/delivery_services/edit.html.haml +11 -5
- data/app/views/tienda/delivery_services/index.html.haml +34 -24
- data/app/views/tienda/delivery_services/new.html.haml +12 -3
- data/app/views/tienda/orders/_form.html.haml +78 -53
- data/app/views/tienda/orders/_order_details.html.haml +57 -54
- data/app/views/tienda/orders/_order_items.html.haml +5 -3
- data/app/views/tienda/orders/_payments_form.html.haml +18 -14
- data/app/views/tienda/orders/_payments_table.html.haml +6 -5
- data/app/views/tienda/orders/_search_form.html.haml +40 -24
- data/app/views/tienda/orders/_status_bar.html.haml +36 -32
- data/app/views/tienda/orders/index.html.haml +41 -34
- data/app/views/tienda/orders/new.html.haml +22 -11
- data/app/views/tienda/orders/show.html.haml +24 -18
- data/app/views/tienda/product_categories/_form.html.haml +34 -22
- data/app/views/tienda/product_categories/edit.html.haml +12 -4
- data/app/views/tienda/product_categories/index.html.haml +26 -16
- data/app/views/tienda/product_categories/new.html.haml +11 -3
- data/app/views/tienda/products/_form.html.haml +163 -126
- data/app/views/tienda/products/_table.html.haml +49 -40
- data/app/views/tienda/products/edit.html.haml +14 -6
- data/app/views/tienda/products/index.html.haml +35 -7
- data/app/views/tienda/sessions/new.html.haml +8 -6
- data/app/views/tienda/sessions/reset.html.haml +5 -5
- data/app/views/tienda/settings/edit.html.haml +20 -14
- data/app/views/tienda/stock_level_adjustments/_table.html.haml +33 -0
- data/app/views/tienda/stock_level_adjustments/index.html.haml +20 -39
- data/app/views/tienda/tax_rates/form.html.haml +41 -25
- data/app/views/tienda/tax_rates/index.html.haml +23 -13
- data/app/views/tienda/users/_form.html.haml +36 -24
- data/app/views/tienda/users/edit.html.haml +12 -3
- data/app/views/tienda/users/index.html.haml +23 -13
- data/app/views/tienda/users/new.html.haml +10 -3
- data/app/views/tienda/variants/form.html.haml +98 -57
- data/app/views/tienda/variants/index.html.haml +47 -29
- data/config/initializers/assets.rb +9 -0
- data/config/locales/en.yml +3 -2
- data/config/routes.rb +1 -1
- data/db/migrate/20150517191600_add_stock_counter_cache.rb +5 -0
- data/db/migrate/20150517195800_remove_stock_level_item_polymorphism.rb +6 -0
- data/db/migrate/20150517212100_update_stock_counter_cache.rb +5 -0
- data/db/migrate/20150603235417_add_document_to_orders.rb +5 -0
- data/lib/tienda/default_navigation.rb +9 -8
- data/lib/tienda/navigation_manager.rb +2 -5
- data/lib/tienda/version.rb +1 -1
- data/lib/tienda.rb +2 -6
- metadata +54 -65
data/app/models/tienda/order.rb
CHANGED
@@ -13,17 +13,17 @@ module Tienda
|
|
13
13
|
require_dependency 'tienda/order/delivery'
|
14
14
|
|
15
15
|
# All items which make up this order
|
16
|
-
has_many :order_items, :
|
17
|
-
accepts_nested_attributes_for :order_items, :
|
16
|
+
has_many :order_items, dependent: :destroy, class_name: 'Tienda::OrderItem'
|
17
|
+
accepts_nested_attributes_for :order_items, allow_destroy: true, reject_if: Proc.new { |a| a['ordered_item_id'].blank? }
|
18
18
|
|
19
19
|
# All products which are part of this order (accessed through the items)
|
20
|
-
has_many :products, :
|
20
|
+
has_many :products, through: :order_items, class_name: 'Tienda::Product', source: :ordered_item, source_type: 'Tienda::Product'
|
21
21
|
|
22
22
|
# Validations
|
23
|
-
validates :token, :
|
24
|
-
with_options :
|
25
|
-
order.validates :email_address, :
|
26
|
-
order.validates :phone_number, :
|
23
|
+
validates :token, presence: true
|
24
|
+
with_options if: Proc.new { |o| !o.building? } do |order|
|
25
|
+
order.validates :email_address, format: { with: /\A\b[A-Z0-9\.\_\%\-\+]+@(?:[A-Z0-9\-]+\.)+[A-Z]{2,6}\b\z/i }
|
26
|
+
order.validates :phone_number, format: { with: /\A[\d\ \-x\(\)]{7,}\z/ }
|
27
27
|
end
|
28
28
|
|
29
29
|
# Set some defaults
|
@@ -82,7 +82,7 @@ module Tienda
|
|
82
82
|
end
|
83
83
|
|
84
84
|
def self.ransackable_attributes(auth_object = nil)
|
85
|
-
[
|
85
|
+
['id', 'billing_postcode', 'billing_address1', 'billing_address2', 'billing_address3', 'billing_address4', 'first_name', 'last_name', 'company', 'email_address', 'phone_number', 'consignment_number', 'status', 'received_at'] + _ransackers.keys
|
86
86
|
end
|
87
87
|
|
88
88
|
def self.ransackable_associations(auth_object = nil)
|
@@ -6,17 +6,17 @@ module Tienda
|
|
6
6
|
# The associated order
|
7
7
|
#
|
8
8
|
# @return [Tienda::Order]
|
9
|
-
belongs_to :order, :
|
9
|
+
belongs_to :order, class_name: 'Tienda::Order', touch: true
|
10
10
|
|
11
11
|
# The item which has been ordered
|
12
|
-
belongs_to :ordered_item, :
|
12
|
+
belongs_to :ordered_item, polymorphic: true
|
13
13
|
|
14
14
|
# Any stock level adjustments which have been made for this order item
|
15
|
-
has_many :stock_level_adjustments, :
|
15
|
+
has_many :stock_level_adjustments, as: :parent, dependent: :nullify, class_name: 'Tienda::StockLevelAdjustment'
|
16
16
|
|
17
17
|
# Validations
|
18
|
-
validates :quantity, :
|
19
|
-
validates :ordered_item, :
|
18
|
+
validates :quantity, numericality: true
|
19
|
+
validates :ordered_item, presence: true
|
20
20
|
|
21
21
|
validate do
|
22
22
|
unless in_stock?
|
@@ -46,13 +46,13 @@ module Tienda
|
|
46
46
|
# @param quantity [Fixnum] the number of items to order
|
47
47
|
# @return [Tienda::OrderItem]
|
48
48
|
def self.add_item(ordered_item, quantity = 1)
|
49
|
-
raise Errors::UnorderableItem, :
|
49
|
+
raise Errors::UnorderableItem, ordered_item: ordered_item unless ordered_item.orderable?
|
50
50
|
transaction do
|
51
|
-
if existing = self.where(:
|
51
|
+
if existing = self.where(ordered_item_id: ordered_item.id, ordered_item_type: ordered_item.class.to_s).first
|
52
52
|
existing.increase!(quantity)
|
53
53
|
existing
|
54
54
|
else
|
55
|
-
new_item = self.create(:
|
55
|
+
new_item = self.create(ordered_item: ordered_item, quantity: 0)
|
56
56
|
new_item.increase!(quantity)
|
57
57
|
new_item
|
58
58
|
end
|
@@ -79,7 +79,7 @@ module Tienda
|
|
79
79
|
transaction do
|
80
80
|
self.quantity += amount
|
81
81
|
unless self.in_stock?
|
82
|
-
raise Tienda::Errors::NotEnoughStock, :
|
82
|
+
raise Tienda::Errors::NotEnoughStock, ordered_item: self.ordered_item, requested_stock: self.quantity
|
83
83
|
end
|
84
84
|
self.save!
|
85
85
|
self.order.remove_delivery_service_if_invalid
|
@@ -195,7 +195,7 @@ module Tienda
|
|
195
195
|
# @return [Boolean]
|
196
196
|
def in_stock?
|
197
197
|
if self.ordered_item && self.ordered_item.stock_control?
|
198
|
-
self.ordered_item.
|
198
|
+
self.ordered_item.stock_count >= unallocated_stock
|
199
199
|
else
|
200
200
|
true
|
201
201
|
end
|
@@ -231,7 +231,7 @@ module Tienda
|
|
231
231
|
# Allocate any unallocated stock for this order item. There is no return value.
|
232
232
|
def allocate_unallocated_stock!
|
233
233
|
if self.ordered_item.stock_control? && self.unallocated_stock != 0
|
234
|
-
self.ordered_item.stock_level_adjustments.create!(:
|
234
|
+
self.ordered_item.stock_level_adjustments.create!(parent: self, adjustment: 0 - self.unallocated_stock, description: "Order ##{self.order.number}")
|
235
235
|
end
|
236
236
|
end
|
237
237
|
|
@@ -3,8 +3,6 @@ require 'roo'
|
|
3
3
|
module Tienda
|
4
4
|
class Product < ActiveRecord::Base
|
5
5
|
|
6
|
-
self.table_name = 'tienda_products'
|
7
|
-
|
8
6
|
# Add dependencies for products
|
9
7
|
require_dependency 'tienda/product/product_attributes'
|
10
8
|
require_dependency 'tienda/product/variants'
|
@@ -17,49 +15,61 @@ module Tienda
|
|
17
15
|
attachment :fifth_image
|
18
16
|
attachment :data_sheet
|
19
17
|
|
18
|
+
# To preserve backwards compatibility
|
19
|
+
alias_attribute :stock, :stock_count
|
20
|
+
|
20
21
|
# The product's category
|
21
22
|
#
|
22
23
|
# @return [Tienda::ProductCategory]
|
23
|
-
belongs_to :product_category, :
|
24
|
+
belongs_to :product_category, class_name: 'Tienda::ProductCategory'
|
24
25
|
|
25
26
|
# The product's tax rate
|
26
27
|
#
|
27
28
|
# @return [Tienda::TaxRate]
|
28
|
-
belongs_to :tax_rate, :
|
29
|
+
belongs_to :tax_rate, class_name: "Tienda::TaxRate"
|
29
30
|
|
30
31
|
# Ordered items which are associated with this product
|
31
|
-
has_many :order_items, :
|
32
|
+
has_many :order_items, dependent: :restrict_with_exception, class_name: 'Tienda::OrderItem', as: :ordered_item
|
32
33
|
|
33
34
|
# Orders which have ordered this product
|
34
|
-
has_many :orders, :
|
35
|
+
has_many :orders, through: :order_items, class_name: 'Tienda::Order'
|
35
36
|
|
36
37
|
# Stock level adjustments for this product
|
37
|
-
has_many :stock_level_adjustments, :
|
38
|
+
has_many :stock_level_adjustments, dependent: :destroy
|
38
39
|
|
39
40
|
# Validations
|
40
|
-
with_options :
|
41
|
-
product.validates :product_category_id, :
|
42
|
-
product.validates :description, :
|
43
|
-
product.validates :short_description, :
|
41
|
+
with_options if: Proc.new { |p| p.parent.nil? } do |product|
|
42
|
+
product.validates :product_category_id, presence: true
|
43
|
+
product.validates :description, presence: true
|
44
|
+
product.validates :short_description, presence: true
|
44
45
|
end
|
45
|
-
validates :name, :
|
46
|
-
validates :permalink, :
|
47
|
-
validates :sku, :
|
48
|
-
validates :weight, :
|
49
|
-
validates :price, :
|
50
|
-
validates :cost_price, :
|
46
|
+
validates :name, presence: true
|
47
|
+
validates :permalink, presence: true, uniqueness: true, permalink: true
|
48
|
+
validates :sku, presence: true
|
49
|
+
validates :weight, numericality: true
|
50
|
+
validates :price, numericality: true
|
51
|
+
validates :cost_price, numericality: true, allow_blank: true
|
51
52
|
|
52
53
|
# Before validation, set the permalink if we don't already have one
|
53
54
|
before_validation { self.permalink = self.name.parameterize if self.permalink.blank? && self.name.is_a?(String) }
|
54
55
|
|
55
56
|
# All active products
|
56
|
-
scope :active, -> { where(:
|
57
|
+
scope :active, -> { where(active: true) }
|
58
|
+
|
59
|
+
# All inactive products
|
60
|
+
scope :inactive, -> { where(active: false) }
|
61
|
+
|
62
|
+
# All in stock products
|
63
|
+
scope :in_stock, -> { where('stock_count > 0') }
|
64
|
+
|
65
|
+
# All not in stock products
|
66
|
+
scope :no_stock, -> { where(stock_count: 0) }
|
57
67
|
|
58
68
|
# All featured products
|
59
|
-
scope :featured, -> {where(:
|
69
|
+
scope :featured, -> { where(featured: true) }
|
60
70
|
|
61
71
|
# All products ordered with default items first followed by name ascending
|
62
|
-
scope :ordered, -> {order(:
|
72
|
+
scope :ordered, -> { order(default: :desc, name: :asc) }
|
63
73
|
|
64
74
|
# Return the name of the product
|
65
75
|
#
|
@@ -88,14 +98,7 @@ module Tienda
|
|
88
98
|
#
|
89
99
|
# @return [Boolean]
|
90
100
|
def in_stock?
|
91
|
-
self.default_variant ? self.default_variant.in_stock? : (stock_control? ?
|
92
|
-
end
|
93
|
-
|
94
|
-
# Return the total number of items currently in stock
|
95
|
-
#
|
96
|
-
# @return [Fixnum]
|
97
|
-
def stock
|
98
|
-
self.stock_level_adjustments.sum(:adjustment)
|
101
|
+
self.default_variant ? self.default_variant.in_stock? : (stock_control? ? stock_count > 0 : true)
|
99
102
|
end
|
100
103
|
|
101
104
|
# Return all product images
|
@@ -113,8 +116,8 @@ module Tienda
|
|
113
116
|
#
|
114
117
|
# @return [Enumerable]
|
115
118
|
def self.with_attributes(key, values)
|
116
|
-
product_ids = Tienda::ProductAttribute.searchable.where(:
|
117
|
-
where(:
|
119
|
+
product_ids = Tienda::ProductAttribute.searchable.where(key: key, value: values).pluck(:product_id).uniq
|
120
|
+
where(id: product_ids)
|
118
121
|
end
|
119
122
|
|
120
123
|
# Imports products from a spreadsheet file
|
@@ -133,35 +136,16 @@ module Tienda
|
|
133
136
|
if product = find_by(name: row["name"])
|
134
137
|
# Dont import products with the same name but update quantities if they're not the same
|
135
138
|
qty = row["qty"].to_i
|
136
|
-
if qty > 0 && qty != product.stock
|
137
|
-
product.stock_level_adjustments.create!(description: I18n.t('tienda.import'), adjustment: qty)
|
138
|
-
end
|
139
|
+
product.stock_level_adjustments.create!(description: I18n.t('tienda.import'), adjustment: qty) if qty > 0 && qty != product.stock
|
139
140
|
else
|
140
|
-
product = new
|
141
|
-
product.
|
142
|
-
|
143
|
-
product.description = row["description"]
|
144
|
-
product.short_description = row["short_description"]
|
145
|
-
product.weight = row["weight"]
|
146
|
-
product.price = row["price"].nil? ? 0 : row["price"]
|
147
|
-
|
148
|
-
product.product_category_id = begin
|
149
|
-
if Tienda::ProductCategory.find_by(name: row["category_name"]).present?
|
150
|
-
# Find and set the category
|
151
|
-
Tienda::ProductCategory.find_by(name: row["category_name"]).id
|
152
|
-
else
|
153
|
-
# Create the category
|
154
|
-
Tienda::ProductCategory.create(name: row["category_name"]).id
|
155
|
-
end
|
156
|
-
end
|
157
|
-
|
141
|
+
product = new(row)
|
142
|
+
product.product_category_id =
|
143
|
+
Tienda::ProductCategory.find_or_create_by(name: row['category_name']).id
|
158
144
|
product.save!
|
159
145
|
|
160
146
|
# Create quantities
|
161
147
|
qty = row["qty"].to_i
|
162
|
-
if qty > 0
|
163
|
-
product.stock_level_adjustments.create!(description: I18n.t('tienda.import'), adjustment: qty)
|
164
|
-
end
|
148
|
+
product.stock_level_adjustments.create!(description: I18n.t('tienda.import'), adjustment: qty) if qty > 0
|
165
149
|
end
|
166
150
|
end
|
167
151
|
end
|
@@ -1,19 +1,21 @@
|
|
1
1
|
module Tienda
|
2
2
|
class StockLevelAdjustment < ActiveRecord::Base
|
3
|
-
|
4
|
-
|
5
|
-
belongs_to :item, :polymorphic => true
|
3
|
+
# The product which the stock level adjustment belongs to
|
4
|
+
belongs_to :product
|
6
5
|
|
7
6
|
# The parent (OrderItem) which the stock level adjustment belongs to
|
8
|
-
belongs_to :parent, :
|
7
|
+
belongs_to :parent, polymorphic: true
|
8
|
+
|
9
|
+
# Save stock cache into Products table
|
10
|
+
counter_culture :product, column_name: :stock_count, delta_column: :adjustment
|
9
11
|
|
10
12
|
# Validations
|
11
|
-
validates :description, :
|
12
|
-
validates :adjustment, :
|
13
|
+
validates :description, presence: true
|
14
|
+
validates :adjustment, numericality: true
|
13
15
|
validate { errors.add(:adjustment, I18n.t('tienda.activerecord.attributes.stock_level_adjustment.must_be_greater_or_equal_zero')) if adjustment == 0 }
|
14
16
|
|
15
17
|
# All stock level adjustments ordered by their created date desending
|
16
|
-
scope :ordered, -> { order(:
|
18
|
+
scope :ordered, -> { order(id: :desc) }
|
17
19
|
|
18
20
|
end
|
19
21
|
end
|
@@ -1,23 +1,21 @@
|
|
1
1
|
module Tienda
|
2
2
|
class TaxRate < ActiveRecord::Base
|
3
3
|
|
4
|
-
self.table_name = 'tienda_tax_rates'
|
5
|
-
|
6
4
|
include Tienda::AssociatedCountries
|
7
5
|
|
8
6
|
# The order address types which may be used when choosing how to apply the tax rate
|
9
7
|
ADDRESS_TYPES = ['billing', 'delivery']
|
10
8
|
|
11
9
|
# Validations
|
12
|
-
validates :name, :
|
13
|
-
validates :address_type, :
|
14
|
-
validates :rate, :
|
10
|
+
validates :name, presence: true
|
11
|
+
validates :address_type, inclusion: {in: ADDRESS_TYPES}
|
12
|
+
validates :rate, numericality: true
|
15
13
|
|
16
14
|
# All products which are assigned to this tax rate
|
17
|
-
has_many :products, :
|
15
|
+
has_many :products, dependent: :restrict_with_exception, class_name: 'Tienda::Product'
|
18
16
|
|
19
17
|
# All delivery service prices which are assigned to this tax rate
|
20
|
-
has_many :delivery_service_prices, :
|
18
|
+
has_many :delivery_service_prices, dependent: :restrict_with_exception, class_name: 'Tienda::DeliveryServicePrice'
|
21
19
|
|
22
20
|
# All tax rates ordered by their ID
|
23
21
|
scope :ordered, -> { order(:id)}
|
data/app/models/tienda/user.rb
CHANGED
@@ -6,9 +6,9 @@ module Tienda
|
|
6
6
|
has_secure_password
|
7
7
|
|
8
8
|
# Validations
|
9
|
-
validates :first_name, :
|
10
|
-
validates :last_name, :
|
11
|
-
validates :email_address, :
|
9
|
+
validates :first_name, presence: true
|
10
|
+
validates :last_name, presence: true
|
11
|
+
validates :email_address, presence: true
|
12
12
|
|
13
13
|
# The user's first name & last name concatenated
|
14
14
|
#
|
@@ -39,7 +39,7 @@ module Tienda
|
|
39
39
|
# @param paassword [String]
|
40
40
|
# @return [Tienda::User]
|
41
41
|
def self.authenticate(email_address, password)
|
42
|
-
user = self.where(:
|
42
|
+
user = self.where(email_address: email_address).first
|
43
43
|
return false if user.nil?
|
44
44
|
return false unless user.authenticate(password)
|
45
45
|
user
|
@@ -1,34 +1,41 @@
|
|
1
1
|
!!!
|
2
|
-
%html
|
2
|
+
%html{lang: I18n.locale}
|
3
3
|
%head
|
4
|
+
%meta{charset: "utf-8"}/
|
5
|
+
%meta{content: "IE=edge", "http-equiv" => "X-UA-Compatible"}/
|
6
|
+
%meta{content: "width=device-width, initial-scale=1", name: "viewport"}/
|
4
7
|
%title #{@page_title} - Tienda
|
5
|
-
|
8
|
+
%meta{content: "http://gonzalo.robaina.me", name: "author"}/
|
9
|
+
=# stylesheet_link_tag 'tienda/application'
|
10
|
+
/ Bootstrap Styles
|
11
|
+
%link{href: '//maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css', rel: 'stylesheet'}
|
12
|
+
/ FontAwesome Styles
|
13
|
+
%link{href: '//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css', rel: 'stylesheet'}
|
14
|
+
/ Morris Chart and Custom Styles
|
15
|
+
= stylesheet_link_tag 'tienda/morris-0.4.3.min', 'tienda/custom-styles'
|
16
|
+
/ Google Fonts
|
17
|
+
%link{:href => "http://fonts.googleapis.com/css?family=Open+Sans", :rel => "stylesheet", :type => "text/css"}/
|
6
18
|
= javascript_include_tag 'tienda/application'
|
7
19
|
= csrf_meta_tags
|
8
20
|
:javascript
|
9
21
|
window.Tienda = {}
|
10
22
|
window.Tienda.currencyUnit = "#{h Tienda.settings.currency_unit}";
|
11
|
-
%body
|
12
|
-
|
13
|
-
|
14
|
-
%h1= link_to "Tienda", root_path
|
15
|
-
%p v#{Tienda::VERSION}
|
16
|
-
%p.logged= t('.logged_in_as', user_name: current_user.full_name)
|
23
|
+
%body{class: body_class}
|
24
|
+
#wrapper
|
25
|
+
= render 'navbar'
|
17
26
|
|
18
|
-
|
19
|
-
- for item in Tienda::NavigationManager.find(:admin_primary).items
|
20
|
-
%li= navigation_manager_link item
|
27
|
+
= render 'sidebar'
|
21
28
|
|
22
|
-
|
29
|
+
#page-wrapper
|
30
|
+
#page-inner
|
31
|
+
= yield
|
23
32
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
= yield
|
31
|
-
|
32
|
-
%footer
|
33
|
-
%p.store= link_to "← #{t('.goto')} #{Tienda.settings.store_name}".html_safe, '/'
|
33
|
+
%footer
|
34
|
+
%p
|
35
|
+
Powered by Tienda Gem by:
|
36
|
+
%a{:href => "http://gonzalo.robaina.me"} Gonzalo Robaina
|
37
|
+
| Template by:
|
38
|
+
%a{:href => "http://webthemez.com"} WebThemez
|
34
39
|
|
40
|
+
%script{src: "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"}
|
41
|
+
= javascript_include_tag 'tienda/jquery.metisMenu', 'tienda/raphael-2.1.0.min', 'tienda/morris'
|
@@ -1,10 +1,48 @@
|
|
1
1
|
!!!
|
2
|
-
%html.
|
2
|
+
%html{lang: I18n.locale}
|
3
3
|
%head
|
4
|
+
%meta{charset: "utf-8"}/
|
5
|
+
%meta{content: "IE=edge", "http-equiv" => "X-UA-Compatible"}/
|
6
|
+
%meta{content: "width=device-width, initial-scale=1", name: "viewport"}/
|
4
7
|
%title #{@page_title} - Tienda
|
5
|
-
%meta{:
|
6
|
-
|
8
|
+
%meta{content: "http://gonzalo.robaina.me", name: "author"}/
|
9
|
+
=# stylesheet_link_tag 'tienda/application'
|
10
|
+
/ Bootstrap Styles
|
11
|
+
%link{href: '//maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css', rel: 'stylesheet'}
|
12
|
+
/ FontAwesome Styles
|
13
|
+
%link{href: '//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css', rel: 'stylesheet'}
|
14
|
+
/ Morris Chart and Custom Styles
|
15
|
+
= stylesheet_link_tag 'tienda/morris-0.4.3.min', 'tienda/custom-styles'
|
16
|
+
/ Google Fonts
|
17
|
+
%link{href: 'http://fonts.googleapis.com/css?family=Open+Sans', rel: 'stylesheet', type: 'text/css'}/
|
7
18
|
= javascript_include_tag 'tienda/application'
|
8
|
-
|
9
|
-
|
10
|
-
=
|
19
|
+
= csrf_meta_tags
|
20
|
+
:javascript
|
21
|
+
window.Tienda = {}
|
22
|
+
window.Tienda.currencyUnit = "#{h Tienda.settings.currency_unit}";
|
23
|
+
%body{class: body_class}
|
24
|
+
|
25
|
+
.container-fluid
|
26
|
+
.row
|
27
|
+
.col-md-4.col-md-offset-4
|
28
|
+
.jumbotron
|
29
|
+
%h1 Tienda
|
30
|
+
|
31
|
+
.row
|
32
|
+
.col-md-4.col-md-offset-4
|
33
|
+
.well
|
34
|
+
= yield
|
35
|
+
|
36
|
+
%footer
|
37
|
+
.row
|
38
|
+
.col-md-4.col-md-offset-4
|
39
|
+
%em Powered by
|
40
|
+
%br
|
41
|
+
Tienda Gem by:
|
42
|
+
%a{:href => "http://gonzalo.robaina.me"} Gonzalo Robaina
|
43
|
+
%br
|
44
|
+
Template by:
|
45
|
+
%a{:href => "http://webthemez.com"} WebThemez
|
46
|
+
|
47
|
+
%script{src: "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"}
|
48
|
+
= javascript_include_tag 'tienda/jquery.metisMenu', 'tienda/raphael-2.1.0.min', 'tienda/morris'
|
@@ -0,0 +1,164 @@
|
|
1
|
+
%nav.navbar.navbar-default.top-navbar{:role => "navigation"}
|
2
|
+
.navbar-header
|
3
|
+
%button.navbar-toggle{"data-target" => ".sidebar-collapse", "data-toggle" => "collapse", :type => "button"}
|
4
|
+
%span.sr-only Toggle navigation
|
5
|
+
%span.icon-bar
|
6
|
+
%span.icon-bar
|
7
|
+
%span.icon-bar
|
8
|
+
%a.navbar-brand{href: root_path}
|
9
|
+
%i.fa.fa-shopping-cart
|
10
|
+
Tienda
|
11
|
+
%ul.nav.navbar-top-links.navbar-right
|
12
|
+
-# %li.dropdown
|
13
|
+
-# %a.dropdown-toggle{"aria-expanded" => "false", "data-toggle" => "dropdown", :href => "#"}
|
14
|
+
-# %i.fa.fa-envelope.fa-fw
|
15
|
+
-# %i.fa.fa-caret-down
|
16
|
+
-# %ul.dropdown-menu.dropdown-messages
|
17
|
+
-# %li
|
18
|
+
-# %a{:href => "#"}
|
19
|
+
-# %div
|
20
|
+
-# %strong John Doe
|
21
|
+
-# %span.pull-right.text-muted
|
22
|
+
-# %em Today
|
23
|
+
-# %div Lorem Ipsum has been the industry's standard dummy text ever since the 1500s...
|
24
|
+
-# %li.divider
|
25
|
+
-# %li
|
26
|
+
-# %a{:href => "#"}
|
27
|
+
-# %div
|
28
|
+
-# %strong John Smith
|
29
|
+
-# %span.pull-right.text-muted
|
30
|
+
-# %em Yesterday
|
31
|
+
-# %div Lorem Ipsum has been the industry's standard dummy text ever since an kwilnw...
|
32
|
+
-# %li.divider
|
33
|
+
-# %li
|
34
|
+
-# %a{:href => "#"}
|
35
|
+
-# %div
|
36
|
+
-# %strong John Smith
|
37
|
+
-# %span.pull-right.text-muted
|
38
|
+
-# %em Yesterday
|
39
|
+
-# %div Lorem Ipsum has been the industry's standard dummy text ever since the...
|
40
|
+
-# %li.divider
|
41
|
+
-# %li
|
42
|
+
-# %a.text-center{:href => "#"}
|
43
|
+
-# %strong Read All Messages
|
44
|
+
-# %i.fa.fa-angle-right
|
45
|
+
-# / /.dropdown-messages
|
46
|
+
-# / /.dropdown
|
47
|
+
-# %li.dropdown
|
48
|
+
-# %a.dropdown-toggle{"aria-expanded" => "false", "data-toggle" => "dropdown", :href => "#"}
|
49
|
+
-# %i.fa.fa-tasks.fa-fw
|
50
|
+
-# %i.fa.fa-caret-down
|
51
|
+
-# %ul.dropdown-menu.dropdown-tasks
|
52
|
+
-# %li
|
53
|
+
-# %a{:href => "#"}
|
54
|
+
-# %div
|
55
|
+
-# %p
|
56
|
+
-# %strong Task 1
|
57
|
+
-# %span.pull-right.text-muted 60% Complete
|
58
|
+
-# .progress.progress-striped.active
|
59
|
+
-# .progress-bar.progress-bar-success{"aria-valuemax" => "100", "aria-valuemin" => "0", "aria-valuenow" => "60", :role => "progressbar", :style => "width: 60%"}
|
60
|
+
-# %span.sr-only 60% Complete (success)
|
61
|
+
-# %li.divider
|
62
|
+
-# %li
|
63
|
+
-# %a{:href => "#"}
|
64
|
+
-# %div
|
65
|
+
-# %p
|
66
|
+
-# %strong Task 2
|
67
|
+
-# %span.pull-right.text-muted 28% Complete
|
68
|
+
-# .progress.progress-striped.active
|
69
|
+
-# .progress-bar.progress-bar-info{"aria-valuemax" => "100", "aria-valuemin" => "0", "aria-valuenow" => "28", :role => "progressbar", :style => "width: 28%"}
|
70
|
+
-# %span.sr-only 28% Complete
|
71
|
+
-# %li.divider
|
72
|
+
-# %li
|
73
|
+
-# %a{:href => "#"}
|
74
|
+
-# %div
|
75
|
+
-# %p
|
76
|
+
-# %strong Task 3
|
77
|
+
-# %span.pull-right.text-muted 60% Complete
|
78
|
+
-# .progress.progress-striped.active
|
79
|
+
-# .progress-bar.progress-bar-warning{"aria-valuemax" => "100", "aria-valuemin" => "0", "aria-valuenow" => "60", :role => "progressbar", :style => "width: 60%"}
|
80
|
+
-# %span.sr-only 60% Complete (warning)
|
81
|
+
-# %li.divider
|
82
|
+
-# %li
|
83
|
+
-# %a{:href => "#"}
|
84
|
+
-# %div
|
85
|
+
-# %p
|
86
|
+
-# %strong Task 4
|
87
|
+
-# %span.pull-right.text-muted 85% Complete
|
88
|
+
-# .progress.progress-striped.active
|
89
|
+
-# .progress-bar.progress-bar-danger{"aria-valuemax" => "100", "aria-valuemin" => "0", "aria-valuenow" => "85", :role => "progressbar", :style => "width: 85%"}
|
90
|
+
-# %span.sr-only 85% Complete (danger)
|
91
|
+
-# %li.divider
|
92
|
+
-# %li
|
93
|
+
-# %a.text-center{:href => "#"}
|
94
|
+
-# %strong See All Tasks
|
95
|
+
-# %i.fa.fa-angle-right
|
96
|
+
-# / /.dropdown-tasks
|
97
|
+
-# / /.dropdown
|
98
|
+
-# %li.dropdown
|
99
|
+
-# %a.dropdown-toggle{"aria-expanded" => "false", "data-toggle" => "dropdown", :href => "#"}
|
100
|
+
-# %i.fa.fa-bell.fa-fw
|
101
|
+
-# %i.fa.fa-caret-down
|
102
|
+
-# %ul.dropdown-menu.dropdown-alerts
|
103
|
+
-# %li
|
104
|
+
-# %a{:href => "#"}
|
105
|
+
-# %div
|
106
|
+
-# %i.fa.fa-comment.fa-fw
|
107
|
+
-# New Comment
|
108
|
+
-# %span.pull-right.text-muted.small 4 min
|
109
|
+
-# %li.divider
|
110
|
+
-# %li
|
111
|
+
-# %a{:href => "#"}
|
112
|
+
-# %div
|
113
|
+
-# %i.fa.fa-twitter.fa-fw
|
114
|
+
-# 3 New Followers
|
115
|
+
-# %span.pull-right.text-muted.small 12 min
|
116
|
+
-# %li.divider
|
117
|
+
-# %li
|
118
|
+
-# %a{:href => "#"}
|
119
|
+
-# %div
|
120
|
+
-# %i.fa.fa-envelope.fa-fw
|
121
|
+
-# Message Sent
|
122
|
+
-# %span.pull-right.text-muted.small 4 min
|
123
|
+
-# %li.divider
|
124
|
+
-# %li
|
125
|
+
-# %a{:href => "#"}
|
126
|
+
-# %div
|
127
|
+
-# %i.fa.fa-tasks.fa-fw
|
128
|
+
-# New Task
|
129
|
+
-# %span.pull-right.text-muted.small 4 min
|
130
|
+
-# %li.divider
|
131
|
+
-# %li
|
132
|
+
-# %a{:href => "#"}
|
133
|
+
-# %div
|
134
|
+
-# %i.fa.fa-upload.fa-fw
|
135
|
+
-# Server Rebooted
|
136
|
+
-# %span.pull-right.text-muted.small 4 min
|
137
|
+
-# %li.divider
|
138
|
+
-# %li
|
139
|
+
-# %a.text-center{:href => "#"}
|
140
|
+
-# %strong See All Alerts
|
141
|
+
-# %i.fa.fa-angle-right
|
142
|
+
/ /.dropdown-alerts
|
143
|
+
/ /.dropdown
|
144
|
+
%li.dropdown
|
145
|
+
%a.dropdown-toggle{"aria-expanded" => "false", "data-toggle" => "dropdown", :href => "#"}
|
146
|
+
%i.fa.fa-user.fa-fw
|
147
|
+
%i.fa.fa-caret-down
|
148
|
+
%ul.dropdown-menu.dropdown-user
|
149
|
+
%li
|
150
|
+
%a{:href => "#"}
|
151
|
+
%i.fa.fa-user.fa-fw
|
152
|
+
User Profile
|
153
|
+
%li
|
154
|
+
%a{:href => "#"}
|
155
|
+
%i.fa.fa-gear.fa-fw
|
156
|
+
Settings
|
157
|
+
%li.divider
|
158
|
+
%li
|
159
|
+
%a{href: logout_path, data: { method: :delete }}
|
160
|
+
%i.fa.fa-sign-out.fa-fw
|
161
|
+
= t('.logout')
|
162
|
+
/ /.dropdown-user
|
163
|
+
/ /.dropdown
|
164
|
+
/ /. NAV TOP
|