mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-02-27 01:43:22 +00:00
Auto-merged master into uk/trial-length on deployment.
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -39,3 +39,4 @@ NERD_tree*
|
||||
coverage
|
||||
libpeerconnection.log
|
||||
/config/application.yml
|
||||
node_modules
|
||||
|
||||
13
.travis.yml
13
.travis.yml
@@ -26,13 +26,16 @@ before_script:
|
||||
- cp config/database.travis.yml config/database.yml
|
||||
- cp config/application.yml.example config/application.yml
|
||||
- RAILS_ENV=test bundle exec rake db:create db:schema:load
|
||||
|
||||
# Only install PhantomJS if it is not already present (ie. cached)
|
||||
- npm list -g phantomjs-prebuilt@~2.1.7 --depth=0 || npm install -g phantomjs-prebuilt@~2.1.7
|
||||
- export PATH=`npm bin -g`:$PATH
|
||||
|
||||
- >
|
||||
if [ "$KARMA" = "true" ]; then
|
||||
npm install karma@0.12.31
|
||||
npm install karma-jasmine@0.1.5
|
||||
npm install karma-phantomjs-launcher@0.1.4
|
||||
npm install karma-coffee-preprocessor@0.2.1
|
||||
npm install -g karma-cli@0.0.4
|
||||
npm install -g npm@'3.8.8'
|
||||
npm install
|
||||
npm install -g karma-cli@0.1.2
|
||||
fi
|
||||
|
||||
script:
|
||||
|
||||
2
Gemfile
2
Gemfile
@@ -28,7 +28,7 @@ gem 'comfortable_mexican_sofa'
|
||||
gem 'simple_form', :github => 'RohanM/simple_form'
|
||||
|
||||
gem 'unicorn'
|
||||
gem 'angularjs-rails', '1.2.13'
|
||||
gem 'angularjs-rails', '1.5.5'
|
||||
gem 'bugsnag'
|
||||
gem 'newrelic_rpm'
|
||||
gem 'haml'
|
||||
|
||||
15
Gemfile.lock
15
Gemfile.lock
@@ -153,7 +153,7 @@ GEM
|
||||
sprockets (~> 2)
|
||||
tilt
|
||||
angularjs-file-upload-rails (1.1.0)
|
||||
angularjs-rails (1.2.13)
|
||||
angularjs-rails (1.5.5)
|
||||
ansi (1.4.2)
|
||||
arel (3.0.3)
|
||||
atomic (1.1.99)
|
||||
@@ -176,7 +176,8 @@ GEM
|
||||
columnize (~> 0.3)
|
||||
debugger-linecache (~> 1.2)
|
||||
cancan (1.6.8)
|
||||
capybara (2.5.0)
|
||||
capybara (2.7.1)
|
||||
addressable
|
||||
mime-types (>= 1.16)
|
||||
nokogiri (>= 1.3.3)
|
||||
rack (>= 1.0.0)
|
||||
@@ -455,7 +456,7 @@ GEM
|
||||
railties (>= 3.1)
|
||||
money (5.1.1)
|
||||
i18n (~> 0.6.0)
|
||||
multi_json (1.11.2)
|
||||
multi_json (1.12.0)
|
||||
multi_xml (0.5.5)
|
||||
newrelic_rpm (3.12.0.288)
|
||||
nokogiri (1.6.7.2)
|
||||
@@ -479,7 +480,7 @@ GEM
|
||||
paypal-sdk-merchant (1.106.1)
|
||||
paypal-sdk-core (~> 0.2.3)
|
||||
pg (0.13.2)
|
||||
poltergeist (1.7.0)
|
||||
poltergeist (1.9.0)
|
||||
capybara (~> 2.1)
|
||||
cliver (~> 0.3.1)
|
||||
multi_json (~> 1.0)
|
||||
@@ -626,7 +627,7 @@ GEM
|
||||
webmock (1.13.0)
|
||||
addressable (>= 2.2.7)
|
||||
crack (>= 0.3.2)
|
||||
websocket-driver (0.6.2)
|
||||
websocket-driver (0.6.3)
|
||||
websocket-extensions (>= 0.1.0)
|
||||
websocket-extensions (0.1.2)
|
||||
whenever (0.9.2)
|
||||
@@ -650,7 +651,7 @@ DEPENDENCIES
|
||||
andand
|
||||
angular-rails-templates (~> 0.2.0)
|
||||
angularjs-file-upload-rails (~> 1.1.0)
|
||||
angularjs-rails (= 1.2.13)
|
||||
angularjs-rails (= 1.5.5)
|
||||
atomic
|
||||
awesome_print
|
||||
aws-sdk
|
||||
@@ -734,4 +735,4 @@ DEPENDENCIES
|
||||
wkhtmltopdf-binary
|
||||
|
||||
BUNDLED WITH
|
||||
1.10.6
|
||||
1.11.2
|
||||
|
||||
@@ -43,9 +43,9 @@
|
||||
//= require ./utils/utils
|
||||
//= require ./users/users
|
||||
//= require ./variant_overrides/variant_overrides
|
||||
//= require textAngular.min.js
|
||||
//= require textAngular-rangy.min.js
|
||||
//= require textAngular-sanitize.min.js
|
||||
//= require ../shared/bindonce.min.js
|
||||
//= require textAngular.min.js
|
||||
//= require darkswarm/i18n.js
|
||||
//= require darkswarm/i18n.translate.js
|
||||
|
||||
|
||||
@@ -1,222 +0,0 @@
|
||||
angular.module("ofn.admin").controller "AdminOrderMgmtCtrl", [
|
||||
"$scope", "$http", "$filter", "dataFetcher", "blankOption", "pendingChanges", "VariantUnitManager", "OptionValueNamer", "SpreeApiKey", "Columns"
|
||||
($scope, $http, $filter, dataFetcher, blankOption, pendingChanges, VariantUnitManager, OptionValueNamer, SpreeApiKey, Columns) ->
|
||||
$scope.loading = true
|
||||
|
||||
$scope.initialiseVariables = ->
|
||||
start = daysFromToday -7
|
||||
end = daysFromToday 1
|
||||
$scope.lineItems = []
|
||||
$scope.filteredLineItems = []
|
||||
$scope.confirmDelete = true
|
||||
$scope.startDate = formatDate start
|
||||
$scope.endDate = formatDate end
|
||||
$scope.quickSearch = ""
|
||||
$scope.bulkActions = [ { name: t("bom_actions_delete"), callback: $scope.deleteLineItems } ]
|
||||
$scope.selectedBulkAction = $scope.bulkActions[0]
|
||||
$scope.selectedUnitsProduct = {};
|
||||
$scope.selectedUnitsVariant = {};
|
||||
$scope.sharedResource = false
|
||||
$scope.columns = Columns.setColumns
|
||||
order_no: { name: t("bom_no"), visible: false }
|
||||
full_name: { name: t("name"), visible: true }
|
||||
email: { name: t("email"), visible: false }
|
||||
phone: { name: t("phone"), visible: false }
|
||||
order_date: { name: t("bom_date"), visible: true }
|
||||
producer: { name: t("producer"), visible: true }
|
||||
order_cycle: { name: t("bom_cycle"), visible: false }
|
||||
hub: { name: t("bom_hub"), visible: false }
|
||||
variant: { name: t("bom_variant"), visible: true }
|
||||
quantity: { name: t("bom_quantity"), visible: true }
|
||||
max: { name: t("bom_max"), visible: true }
|
||||
final_weight_volume: { name: t("bom_final_weigth_volume"), visible: false }
|
||||
price: { name: t("price"), visible: false }
|
||||
$scope.initialise = ->
|
||||
$scope.initialiseVariables()
|
||||
authorise_api_reponse = ""
|
||||
dataFetcher("/api/users/authorise_api?token=" + SpreeApiKey).then (data) ->
|
||||
authorise_api_reponse = data
|
||||
$scope.spree_api_key_ok = data.hasOwnProperty("success") and data["success"] == "Use of API Authorised"
|
||||
if $scope.spree_api_key_ok
|
||||
$http.defaults.headers.common["X-Spree-Token"] = SpreeApiKey
|
||||
dataFetcher("/api/enterprises/accessible?template=bulk_index&q[is_primary_producer_eq]=true").then (data) ->
|
||||
$scope.suppliers = $filter('orderBy')(data, 'name')
|
||||
$scope.suppliers.unshift blankOption()
|
||||
dataFetcher("/api/enterprises/accessible?template=bulk_index&q[sells_in][]=own&q[sells_in][]=any").then (data) ->
|
||||
$scope.distributors = $filter('orderBy')(data, 'name')
|
||||
$scope.distributors.unshift blankOption()
|
||||
ocFetcher = dataFetcher("/api/order_cycles/accessible?as=distributor&q[orders_close_at_gt]=#{formatDate(daysFromToday(-90))}").then (data) ->
|
||||
$scope.orderCycles = data
|
||||
$scope.orderCyclesByID = []
|
||||
$scope.orderCyclesByID[oc.id] = oc for oc in $scope.orderCycles
|
||||
$scope.orderCycles.unshift blankOption()
|
||||
$scope.fetchOrders()
|
||||
ocFetcher.then ->
|
||||
$scope.resetSelectFilters()
|
||||
else if authorise_api_reponse.hasOwnProperty("error")
|
||||
$scope.api_error_msg = authorise_api_reponse("error")
|
||||
else
|
||||
api_error_msg = "You don't have an API key yet. An attempt was made to generate one, but you are currently not authorised, please contact your site administrator for access."
|
||||
|
||||
$scope.fetchOrders = ->
|
||||
$scope.loading = true
|
||||
dataFetcher("/admin/orders/managed?template=bulk_index;page=1;per_page=500;q[state_not_eq]=canceled;q[completed_at_not_null]=true;q[completed_at_gt]=#{$scope.startDate};q[completed_at_lt]=#{$scope.endDate}").then (data) ->
|
||||
$scope.resetOrders data
|
||||
$scope.loading = false
|
||||
|
||||
$scope.resetOrders = (data) ->
|
||||
$scope.orders = data
|
||||
$scope.resetLineItems()
|
||||
pendingChanges.removeAll()
|
||||
|
||||
$scope.resetLineItems = ->
|
||||
$scope.lineItems = $scope.orders.reduce (lineItems,order) ->
|
||||
orderWithoutLineItems = $scope.lineItemOrder order
|
||||
for i,line_item of order.line_items
|
||||
line_item.checked = false
|
||||
line_item.supplier = $scope.matchObject $scope.suppliers, line_item.supplier, null
|
||||
line_item.order = orderWithoutLineItems
|
||||
line_item.original_final_weight_volume = line_item.final_weight_volume
|
||||
line_item.original_quantity = line_item.quantity
|
||||
line_item.original_price = line_item.price
|
||||
|
||||
lineItems.concat order.line_items
|
||||
, []
|
||||
|
||||
$scope.lineItemOrder = (order) ->
|
||||
lineItemOrder = angular.copy(order)
|
||||
delete lineItemOrder.line_items
|
||||
lineItemOrder.distributor = $scope.matchObject $scope.distributors, order.distributor, null
|
||||
lineItemOrder.order_cycle = $scope.matchObject $scope.orderCycles, order.order_cycle, null
|
||||
lineItemOrder
|
||||
|
||||
$scope.matchObject = (list, testObject, noMatch) ->
|
||||
for i, object of list
|
||||
if angular.equals(object, testObject)
|
||||
return object
|
||||
return noMatch
|
||||
|
||||
$scope.deleteLineItem = (lineItem) ->
|
||||
if ($scope.confirmDelete && confirm("Are you sure?")) || !$scope.confirmDelete
|
||||
$http(
|
||||
method: "DELETE"
|
||||
url: "/api/orders/" + lineItem.order.number + "/line_items/" + lineItem.id
|
||||
).success (data) ->
|
||||
$scope.lineItems.splice $scope.lineItems.indexOf(lineItem), 1
|
||||
|
||||
$scope.deleteLineItems = (lineItems) ->
|
||||
existingState = $scope.confirmDelete
|
||||
$scope.confirmDelete = false
|
||||
$scope.deleteLineItem lineItem for lineItem in lineItems when lineItem.checked
|
||||
$scope.confirmDelete = existingState
|
||||
|
||||
$scope.submit = ->
|
||||
if $scope.bulk_order_form.$valid
|
||||
pendingChanges.submitAll()
|
||||
else
|
||||
alert "Some errors must be resolved be before you can update orders.\nAny fields with red borders contain errors."
|
||||
|
||||
$scope.allBoxesChecked = ->
|
||||
checkedCount = $scope.filteredLineItems.reduce (count,lineItem) ->
|
||||
count + (if lineItem.checked then 1 else 0 )
|
||||
, 0
|
||||
checkedCount == $scope.filteredLineItems.length
|
||||
|
||||
$scope.toggleAllCheckboxes = ->
|
||||
changeTo = !$scope.allBoxesChecked()
|
||||
lineItem.checked = changeTo for lineItem in $scope.filteredLineItems
|
||||
|
||||
$scope.setSelectedUnitsVariant = (unitsProduct,unitsVariant) ->
|
||||
$scope.selectedUnitsProduct = unitsProduct
|
||||
$scope.selectedUnitsVariant = unitsVariant
|
||||
|
||||
$scope.sumUnitValues = ->
|
||||
sum = $scope.filteredLineItems.reduce (sum,lineItem) ->
|
||||
sum = sum + lineItem.final_weight_volume
|
||||
, 0
|
||||
|
||||
$scope.sumMaxUnitValues = ->
|
||||
sum = $scope.filteredLineItems.reduce (sum,lineItem) ->
|
||||
sum = sum + Math.max(lineItem.max_quantity,lineItem.original_quantity) * lineItem.units_variant.unit_value
|
||||
, 0
|
||||
|
||||
$scope.allFinalWeightVolumesPresent = ->
|
||||
for i,lineItem of $scope.filteredLineItems
|
||||
return false if !lineItem.hasOwnProperty('final_weight_volume') || !(lineItem.final_weight_volume > 0)
|
||||
true
|
||||
|
||||
# How is this different to OptionValueNamer#name?
|
||||
# Should it be extracted to that class or VariantUnitManager?
|
||||
$scope.formattedValueWithUnitName = (value, unitsProduct, unitsVariant) ->
|
||||
# A Units Variant is an API object which holds unit properies of a variant
|
||||
if unitsProduct.hasOwnProperty("variant_unit") && (unitsProduct.variant_unit == "weight" || unitsProduct.variant_unit == "volume") && value > 0
|
||||
scale = VariantUnitManager.getScale(value, unitsProduct.variant_unit)
|
||||
Math.round(value/scale * 1000)/1000 + " " + VariantUnitManager.getUnitName(scale, unitsProduct.variant_unit)
|
||||
else
|
||||
''
|
||||
|
||||
$scope.fulfilled = (sumOfUnitValues) ->
|
||||
# A Units Variant is an API object which holds unit properies of a variant
|
||||
if $scope.selectedUnitsProduct.hasOwnProperty("group_buy_unit_size") && $scope.selectedUnitsProduct.group_buy_unit_size > 0 &&
|
||||
$scope.selectedUnitsProduct.hasOwnProperty("variant_unit") &&
|
||||
( $scope.selectedUnitsProduct.variant_unit == "weight" || $scope.selectedUnitsProduct.variant_unit == "volume" )
|
||||
Math.round( sumOfUnitValues / $scope.selectedUnitsProduct.group_buy_unit_size * 1000)/1000
|
||||
else
|
||||
''
|
||||
|
||||
$scope.unitsVariantSelected = ->
|
||||
!angular.equals($scope.selectedUnitsVariant,{})
|
||||
|
||||
$scope.resetSelectFilters = ->
|
||||
$scope.distributorFilter = $scope.distributors[0].id
|
||||
$scope.supplierFilter = $scope.suppliers[0].id
|
||||
$scope.orderCycleFilter = $scope.orderCycles[0].id
|
||||
$scope.quickSearch = ""
|
||||
|
||||
$scope.weightAdjustedPrice = (lineItem) ->
|
||||
if lineItem.final_weight_volume > 0
|
||||
unit_value = lineItem.final_weight_volume / lineItem.quantity
|
||||
original_unit_value = lineItem.original_final_weight_volume / lineItem.original_quantity
|
||||
lineItem.price = lineItem.original_price * (unit_value / original_unit_value)
|
||||
|
||||
$scope.unitValueLessThanZero = (lineItem) ->
|
||||
if lineItem.units_variant.unit_value <= 0
|
||||
true
|
||||
else
|
||||
false
|
||||
|
||||
$scope.updateOnQuantity = (lineItem) ->
|
||||
if lineItem.quantity > 0
|
||||
lineItem.final_weight_volume = lineItem.original_final_weight_volume * lineItem.quantity / lineItem.original_quantity
|
||||
$scope.weightAdjustedPrice(lineItem)
|
||||
|
||||
$scope.$watch "orderCycleFilter", (newVal, oldVal) ->
|
||||
unless $scope.orderCycleFilter == "0" || angular.equals(newVal, oldVal)
|
||||
$scope.startDate = $scope.orderCyclesByID[$scope.orderCycleFilter].first_order
|
||||
$scope.endDate = $scope.orderCyclesByID[$scope.orderCycleFilter].last_order
|
||||
]
|
||||
|
||||
daysFromToday = (days) ->
|
||||
now = new Date
|
||||
now.setHours(0)
|
||||
now.setMinutes(0)
|
||||
now.setSeconds(0)
|
||||
now.setDate( now.getDate() + days )
|
||||
now
|
||||
|
||||
formatDate = (date) ->
|
||||
year = date.getFullYear()
|
||||
month = twoDigitNumber date.getMonth() + 1
|
||||
day = twoDigitNumber date.getDate()
|
||||
return year + "-" + month + "-" + day
|
||||
|
||||
formatTime = (date) ->
|
||||
hours = twoDigitNumber date.getHours()
|
||||
mins = twoDigitNumber date.getMinutes()
|
||||
secs = twoDigitNumber date.getSeconds()
|
||||
return hours + ":" + mins + ":" + secs
|
||||
|
||||
twoDigitNumber = (number) ->
|
||||
twoDigits = "" + number
|
||||
twoDigits = ("0" + number) if number < 10
|
||||
twoDigits
|
||||
@@ -3,18 +3,7 @@ angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout
|
||||
|
||||
$scope.StatusMessage = StatusMessage
|
||||
|
||||
$scope.columns = Columns.setColumns
|
||||
producer: {name: t("products_producer"), visible: true}
|
||||
sku: {name: t("products_sku"), visible: false}
|
||||
name: {name: t("products_name"), visible: true}
|
||||
unit: {name: t("products_unit"), visible: true}
|
||||
price: {name: t("products_price"), visible: true}
|
||||
on_hand: {name: t("products_on_hand"), visible: true}
|
||||
on_demand: {name: t("products_on_demand"), visible: false}
|
||||
category: {name: t("products_category"), visible: false}
|
||||
tax_category: {name: t("products_tax_category"), visible: false}
|
||||
inherits_properties: {name: t("products_inherits_properties"), visible: false}
|
||||
available_on: {name: t("products_available_on"), visible: false}
|
||||
$scope.columns = Columns.columns
|
||||
|
||||
$scope.variant_unit_options = VariantUnitManager.variantUnitOptions()
|
||||
|
||||
|
||||
@@ -1,33 +1,24 @@
|
||||
angular.module("admin.customers").controller "customersCtrl", ($scope, CustomerResource, Columns, pendingChanges, shops) ->
|
||||
$scope.shop = {}
|
||||
angular.module("admin.customers").controller "customersCtrl", ($scope, $q, Customers, TagRuleResource, CurrentShop, RequestMonitor, Columns, pendingChanges, shops) ->
|
||||
$scope.shops = shops
|
||||
$scope.CurrentShop = CurrentShop
|
||||
$scope.RequestMonitor = RequestMonitor
|
||||
$scope.submitAll = pendingChanges.submitAll
|
||||
$scope.add = Customers.add
|
||||
$scope.deleteCustomer = Customers.remove
|
||||
$scope.customerLimit = 20
|
||||
$scope.columns = Columns.columns
|
||||
|
||||
$scope.columns = Columns.setColumns
|
||||
email: { name: "Email", visible: true }
|
||||
code: { name: "Code", visible: true }
|
||||
tags: { name: "Tags", visible: true }
|
||||
$scope.$watch "CurrentShop.shop", ->
|
||||
if $scope.CurrentShop.shop.id?
|
||||
Customers.index({enterprise_id: $scope.CurrentShop.shop.id}).then (data) ->
|
||||
$scope.customers = data
|
||||
|
||||
$scope.$watch "shop.id", ->
|
||||
if $scope.shop.id?
|
||||
$scope.customers = index {enterprise_id: $scope.shop.id}
|
||||
|
||||
$scope.add = (email) ->
|
||||
$scope.findTags = (query) ->
|
||||
defer = $q.defer()
|
||||
params =
|
||||
enterprise_id: $scope.shop.id
|
||||
email: email
|
||||
CustomerResource.create params, (customer) =>
|
||||
if customer.id
|
||||
$scope.customers.push customer
|
||||
$scope.quickSearch = customer.email
|
||||
|
||||
$scope.deleteCustomer = (customer) ->
|
||||
params = id: customer.id
|
||||
CustomerResource.destroy params, ->
|
||||
i = $scope.customers.indexOf customer
|
||||
$scope.customers.splice i, 1 unless i < 0
|
||||
|
||||
index = (params) ->
|
||||
$scope.loaded = false
|
||||
CustomerResource.index params, =>
|
||||
$scope.loaded = true
|
||||
enterprise_id: $scope.CurrentShop.shop.id
|
||||
TagRuleResource.mapByTag params, (data) =>
|
||||
filtered = data.filter (tag) ->
|
||||
tag.text.toLowerCase().indexOf(query.toLowerCase()) != -1
|
||||
defer.resolve filtered
|
||||
defer.promise
|
||||
|
||||
@@ -1 +1 @@
|
||||
angular.module("admin.customers", ['ngResource', 'ngTagsInput', 'admin.indexUtils', 'admin.utils', 'admin.dropdown'])
|
||||
angular.module("admin.customers", ['ngResource', 'admin.tagRules', 'admin.indexUtils', 'admin.utils', 'admin.dropdown'])
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
angular.module("admin.customers").directive 'newCustomerDialog', ($compile, $injector, $templateCache, $window, CurrentShop, Customers) ->
|
||||
restrict: 'A'
|
||||
scope: true
|
||||
link: (scope, element, attr) ->
|
||||
scope.CurrentShop = CurrentShop
|
||||
scope.submitted = null
|
||||
scope.email = ""
|
||||
scope.errors = []
|
||||
|
||||
scope.addCustomer = (valid) ->
|
||||
scope.submitted = scope.email
|
||||
scope.errors = []
|
||||
if valid
|
||||
Customers.add(scope.email).$promise.then (data) ->
|
||||
if data.id
|
||||
scope.email = ""
|
||||
scope.submitted = null
|
||||
template.dialog('close')
|
||||
, (response) ->
|
||||
if response.data.errors
|
||||
scope.errors.push(error) for error in response.data.errors
|
||||
else
|
||||
scope.errors.push("Sorry! Could not create '#{scope.email}'")
|
||||
return
|
||||
|
||||
# Compile modal template
|
||||
template = $compile($templateCache.get('admin/new_customer_dialog.html'))(scope)
|
||||
|
||||
# Set Dialog options
|
||||
template.dialog
|
||||
show: { effect: "fade", duration: 400 }
|
||||
hide: { effect: "fade", duration: 300 }
|
||||
autoOpen: false
|
||||
resizable: false
|
||||
width: $window.innerWidth * 0.4;
|
||||
modal: true
|
||||
open: (event, ui) ->
|
||||
$('.ui-widget-overlay').bind 'click', ->
|
||||
$(this).siblings('.ui-dialog').find('.ui-dialog-content').dialog('close')
|
||||
|
||||
# Link opening of dialog to click event on element
|
||||
element.bind 'click', (e) ->
|
||||
if CurrentShop.shop.id
|
||||
template.dialog('open')
|
||||
else
|
||||
alert('Please select a shop first')
|
||||
@@ -0,0 +1,3 @@
|
||||
angular.module("admin.customers").factory "CurrentShop", ->
|
||||
new class CurrentShop
|
||||
shop: {}
|
||||
@@ -0,0 +1,21 @@
|
||||
angular.module("admin.customers").factory "Customers", ($q, RequestMonitor, CustomerResource, CurrentShop) ->
|
||||
new class Customers
|
||||
customers: []
|
||||
|
||||
add: (email) ->
|
||||
params =
|
||||
enterprise_id: CurrentShop.shop.id
|
||||
email: email
|
||||
CustomerResource.create params, (customer) =>
|
||||
@customers.unshift customer if customer.id
|
||||
|
||||
remove: (customer) ->
|
||||
params = id: customer.id
|
||||
CustomerResource.destroy params, =>
|
||||
i = @customers.indexOf customer
|
||||
@customers.splice i, 1 unless i < 0
|
||||
|
||||
index: (params) ->
|
||||
request = CustomerResource.index(params, (data) => @customers = data)
|
||||
RequestMonitor.load(request.$promise)
|
||||
request.$promise
|
||||
@@ -1,4 +1,4 @@
|
||||
angular.module("ofn.admin").directive "ofnTrackMaster", ["DirtyProducts", (DirtyProducts) ->
|
||||
angular.module("ofn.admin").directive "ofnTrackMaster", (DirtyProducts) ->
|
||||
require: "ngModel"
|
||||
link: (scope, element, attrs, ngModel) ->
|
||||
ngModel.$parsers.push (viewValue) ->
|
||||
@@ -6,4 +6,3 @@ angular.module("ofn.admin").directive "ofnTrackMaster", ["DirtyProducts", (Dirty
|
||||
DirtyProducts.addMasterProperty scope.product.id, scope.product.master.id, attrs.ofnTrackMaster, viewValue
|
||||
scope.displayDirtyProducts()
|
||||
viewValue
|
||||
]
|
||||
@@ -0,0 +1,10 @@
|
||||
angular.module("admin.dropdown").controller "ColumnsDropdownCtrl", ($scope, Columns) ->
|
||||
$scope.columns = Columns.columns
|
||||
$scope.toggle = Columns.toggleColumn
|
||||
$scope.saved = Columns.preferencesSaved
|
||||
$scope.saving = false
|
||||
|
||||
$scope.saveColumnPreferences = (action_name) ->
|
||||
$scope.saving = true
|
||||
Columns.savePreferences(action_name).then ->
|
||||
$scope.saving = false
|
||||
@@ -0,0 +1,6 @@
|
||||
angular.module("admin.dropdown").directive 'columnsDropdown', ->
|
||||
restrict: 'E'
|
||||
templateUrl: 'admin/columns_dropdown.html'
|
||||
controller: 'ColumnsDropdownCtrl'
|
||||
scope:
|
||||
action: '@'
|
||||
@@ -5,9 +5,4 @@ angular.module("admin.enterprises").controller 'enterprisesCtrl', ($scope, $q, E
|
||||
$q.all(requests).then ->
|
||||
$scope.loaded = true
|
||||
|
||||
$scope.columns = Columns.setColumns
|
||||
name: { name: "Name", visible: true }
|
||||
producer: { name: "Producer", visible: true }
|
||||
package: { name: "Package", visible: true }
|
||||
status: { name: "Status", visible: true }
|
||||
manage: { name: "Manage", visible: true }
|
||||
$scope.columns = Columns.columns
|
||||
|
||||
@@ -1 +1 @@
|
||||
angular.module("admin.enterprises", [
|
||||
angular.module("admin.enterprises", [
|
||||
@@ -1,7 +0,0 @@
|
||||
angular.module('ofn.admin').filter "translate", ->
|
||||
(key, options) ->
|
||||
t(key, options)
|
||||
|
||||
angular.module('ofn.admin').filter "t", ->
|
||||
(key, options) ->
|
||||
t(key, options)
|
||||
@@ -1,4 +1,4 @@
|
||||
angular.module("admin.indexUtils").directive "ofnSelect2", ($sanitize, $timeout) ->
|
||||
angular.module("admin.indexUtils").directive "ofnSelect2", ($sanitize, $timeout, $filter) ->
|
||||
require: 'ngModel'
|
||||
restrict: 'C'
|
||||
scope:
|
||||
@@ -6,15 +6,19 @@ angular.module("admin.indexUtils").directive "ofnSelect2", ($sanitize, $timeout)
|
||||
minSearch: "@?"
|
||||
text: "@?"
|
||||
blank: "=?"
|
||||
filter: "=?"
|
||||
link: (scope, element, attrs, ngModel) ->
|
||||
$timeout ->
|
||||
scope.text ||= 'name'
|
||||
scope.filter ||= -> true
|
||||
scope.data.unshift(scope.blank) if scope.blank? && typeof scope.blank is "object"
|
||||
|
||||
item.name = $sanitize(item.name) for item in scope.data
|
||||
element.select2
|
||||
minimumResultsForSearch: scope.minSearch || 0
|
||||
data: { results: scope.data, text: scope.text }
|
||||
data: ->
|
||||
filtered = $filter('filter')(scope.data,scope.filter)
|
||||
{ results: filtered, text: scope.text }
|
||||
formatSelection: (item) ->
|
||||
item[scope.text]
|
||||
formatResult: (item) ->
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
angular.module("admin.indexUtils").component 'showMore',
|
||||
templateUrl: 'admin/show_more.html'
|
||||
bindings:
|
||||
data: "="
|
||||
limit: "="
|
||||
increment: "="
|
||||
|
||||
# For now, this component is not being used.
|
||||
# Something about binding "data" to a variable on the parent scope that is continually refreshed by
|
||||
# being assigned within an ng-repeat means that we get $digest iteration errors. Seems to be solved
|
||||
# by using the new "as" syntax for ng-repeat to assign and alias the outcome of the filters, but this
|
||||
# has the limitation of not being able to be limited AFTER the assignment has been made, which we need
|
||||
@@ -1,8 +0,0 @@
|
||||
angular.module("admin.indexUtils").directive "toggleColumn", (Columns) ->
|
||||
link: (scope, element, attrs) ->
|
||||
element.addClass "selected" if scope.column.visible
|
||||
|
||||
element.click "click", ->
|
||||
scope.$apply ->
|
||||
Columns.toggleColumn(scope.column)
|
||||
element.toggleClass "selected"
|
||||
@@ -1 +1 @@
|
||||
angular.module("admin.indexUtils", ['ngResource', 'ngSanitize', 'templates']).config ($httpProvider) ->
|
||||
angular.module("admin.indexUtils", ['ngResource', 'ngSanitize', 'templates', 'admin.utils']).config ($httpProvider) ->
|
||||
@@ -1,13 +1,15 @@
|
||||
angular.module("admin.indexUtils").factory 'Columns', ($rootScope) ->
|
||||
angular.module("admin.indexUtils").factory 'Columns', ($rootScope, $http, columns) ->
|
||||
new class Columns
|
||||
savedColumns: {}
|
||||
columns: {}
|
||||
visibleCount: 0
|
||||
|
||||
setColumns: (columns) =>
|
||||
constructor: ->
|
||||
@columns = {}
|
||||
@columns[name] = column for name, column of columns
|
||||
for column in columns
|
||||
@columns[column.column_name] = column
|
||||
@savedColumns[column.column_name] = angular.copy(column)
|
||||
@calculateVisibleCount()
|
||||
@columns
|
||||
|
||||
toggleColumn: (column) =>
|
||||
column.visible = !column.visible
|
||||
@@ -16,3 +18,18 @@ angular.module("admin.indexUtils").factory 'Columns', ($rootScope) ->
|
||||
calculateVisibleCount: =>
|
||||
@visibleCount = (column for name, column of @columns when column.visible).length
|
||||
$rootScope.$broadcast "columnCount:changed", @visibleCount
|
||||
|
||||
preferencesSaved: =>
|
||||
angular.equals(@columns, @savedColumns)
|
||||
|
||||
savePreferences: (action_name) =>
|
||||
$http
|
||||
method: "PUT"
|
||||
url: "/admin/column_preferences/bulk_update"
|
||||
data:
|
||||
action_name: action_name
|
||||
column_preferences: (preference for column_name, preference of @columns)
|
||||
.success (data) =>
|
||||
for column in data
|
||||
angular.extend(@columns[column.column_name], column)
|
||||
angular.extend(@savedColumns[column.column_name], column)
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
angular.module("admin.indexUtils").factory "pendingChanges", (resources) ->
|
||||
angular.module("admin.indexUtils").factory "pendingChanges", ($q, resources, StatusMessage) ->
|
||||
new class pendingChanges
|
||||
pendingChanges: {}
|
||||
errors: []
|
||||
|
||||
add: (id, attr, change) =>
|
||||
@pendingChanges["#{id}"] = {} unless @pendingChanges.hasOwnProperty("#{id}")
|
||||
@pendingChanges["#{id}"]["#{attr}"] = change
|
||||
StatusMessage.display('notice', "You have made #{@changeCount(@pendingChanges)} unsaved changes")
|
||||
|
||||
removeAll: =>
|
||||
@pendingChanges = {}
|
||||
@@ -14,11 +16,19 @@ angular.module("admin.indexUtils").factory "pendingChanges", (resources) ->
|
||||
delete @pendingChanges["#{id}"]["#{attr}"]
|
||||
delete @pendingChanges["#{id}"] if @changeCount( @pendingChanges["#{id}"] ) < 1
|
||||
|
||||
submitAll: =>
|
||||
submitAll: (form=null) =>
|
||||
all = []
|
||||
@errors = []
|
||||
StatusMessage.display('progress', "Saving...")
|
||||
for id, objectChanges of @pendingChanges
|
||||
for attrName, change of objectChanges
|
||||
all.push @submit(change)
|
||||
$q.all(all).then =>
|
||||
if @errors.length == 0
|
||||
StatusMessage.display('success', "All changes saved successfully")
|
||||
form.$setPristine() if form?
|
||||
else
|
||||
StatusMessage.display('failure', "Oh no! I was unable to save your changes")
|
||||
all
|
||||
|
||||
submit: (change) ->
|
||||
@@ -26,7 +36,8 @@ angular.module("admin.indexUtils").factory "pendingChanges", (resources) ->
|
||||
@remove change.object.id, change.attr
|
||||
change.scope.reset( data["#{change.attr}"] )
|
||||
change.scope.success()
|
||||
, (error) ->
|
||||
, (error) =>
|
||||
@errors.push error
|
||||
change.scope.error()
|
||||
|
||||
changeCount: (objectChanges) ->
|
||||
|
||||
@@ -5,27 +5,14 @@ angular.module("admin.lineItems").controller 'LineItemsCtrl', ($scope, $timeout,
|
||||
$scope.confirmDelete = true
|
||||
$scope.startDate = formatDate daysFromToday -7
|
||||
$scope.endDate = formatDate daysFromToday 1
|
||||
$scope.bulkActions = [ { name: t("bom_actions_delete"), callback: 'deleteLineItems' } ]
|
||||
$scope.bulkActions = [ { name: t("admin.orders.bulk_management.actions_delete"), callback: 'deleteLineItems' } ]
|
||||
$scope.selectedUnitsProduct = {}
|
||||
$scope.selectedUnitsVariant = {}
|
||||
$scope.sharedResource = false
|
||||
$scope.columns = Columns.setColumns
|
||||
order_no: { name: t("bom_no"), visible: false }
|
||||
full_name: { name: t("name"), visible: true }
|
||||
email: { name: t("email"), visible: false }
|
||||
phone: { name: t("phone"), visible: false }
|
||||
order_date: { name: t("bom_date"), visible: true }
|
||||
producer: { name: t("producer"), visible: true }
|
||||
order_cycle: { name: t("bom_cycle"), visible: false }
|
||||
hub: { name: t("bom_hub"), visible: false }
|
||||
variant: { name: t("bom_variant"), visible: true }
|
||||
quantity: { name: t("bom_quantity"), visible: true }
|
||||
max: { name: t("bom_max"), visible: true }
|
||||
final_weight_volume: { name: t("bom_final_weigth_volume"), visible: false }
|
||||
price: { name: t("price"), visible: false }
|
||||
$scope.columns = Columns.columns
|
||||
|
||||
$scope.confirmRefresh = ->
|
||||
LineItems.allSaved() || confirm(t "unsaved_changes_warning")
|
||||
LineItems.allSaved() || confirm(t("unsaved_changes_warning"))
|
||||
|
||||
$scope.resetSelectFilters = ->
|
||||
$scope.distributorFilter = blankOption().id
|
||||
|
||||
@@ -12,7 +12,7 @@ angular.module('admin.orderCycles')
|
||||
$scope.StatusMessage = StatusMessage
|
||||
|
||||
$scope.loaded = ->
|
||||
Enterprise.loaded && EnterpriseFee.loaded
|
||||
Enterprise.loaded && EnterpriseFee.loaded && OrderCycle.loaded
|
||||
|
||||
$scope.suppliedVariants = (enterprise_id) ->
|
||||
Enterprise.suppliedVariants(enterprise_id)
|
||||
@@ -79,5 +79,6 @@ angular.module('admin.orderCycles')
|
||||
$scope.removeDistributionOfVariant = (variant_id) ->
|
||||
OrderCycle.removeDistributionOfVariant(variant_id)
|
||||
|
||||
$scope.submit = (destination) ->
|
||||
$scope.submit = ($event, destination) ->
|
||||
$event.preventDefault()
|
||||
OrderCycle.create(destination)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
angular.module('admin.orderCycles')
|
||||
.controller 'AdminEditOrderCycleCtrl', ($scope, $filter, $location, OrderCycle, Enterprise, EnterpriseFee, StatusMessage) ->
|
||||
.controller 'AdminEditOrderCycleCtrl', ($scope, $filter, $location, $window, OrderCycle, Enterprise, EnterpriseFee, StatusMessage) ->
|
||||
order_cycle_id = $location.absUrl().match(/\/admin\/order_cycles\/(\d+)/)[1]
|
||||
$scope.enterprises = Enterprise.index(order_cycle_id: order_cycle_id)
|
||||
$scope.supplier_enterprises = Enterprise.producer_enterprises
|
||||
@@ -12,6 +12,9 @@ angular.module('admin.orderCycles')
|
||||
|
||||
$scope.StatusMessage = StatusMessage
|
||||
|
||||
$scope.$watch 'order_cycle_form.$dirty', (newValue) ->
|
||||
StatusMessage.display 'notice', 'You have unsaved changes' if newValue
|
||||
|
||||
$scope.loaded = ->
|
||||
Enterprise.loaded && EnterpriseFee.loaded && OrderCycle.loaded
|
||||
|
||||
@@ -60,6 +63,7 @@ angular.module('admin.orderCycles')
|
||||
$scope.removeExchange = ($event, exchange) ->
|
||||
$event.preventDefault()
|
||||
OrderCycle.removeExchange(exchange)
|
||||
$scope.order_cycle_form.$dirty = true
|
||||
|
||||
$scope.addCoordinatorFee = ($event) ->
|
||||
$event.preventDefault()
|
||||
@@ -81,4 +85,13 @@ angular.module('admin.orderCycles')
|
||||
OrderCycle.removeDistributionOfVariant(variant_id)
|
||||
|
||||
$scope.submit = (destination) ->
|
||||
OrderCycle.update(destination)
|
||||
$event.preventDefault()
|
||||
StatusMessage.display 'progress', "Saving..."
|
||||
|
||||
$scope.submit = ($event, destination) ->
|
||||
$event.preventDefault()
|
||||
StatusMessage.display 'progress', "Saving..."
|
||||
OrderCycle.update(destination, $scope.order_cycle_form)
|
||||
|
||||
$scope.cancel = (destination) ->
|
||||
$window.location = destination
|
||||
|
||||
@@ -20,7 +20,7 @@ angular.module('admin.orderCycles').controller "AdminSimpleCreateOrderCycleCtrl"
|
||||
OrderCycle.order_cycle.coordinator_id = enterprise.id
|
||||
|
||||
$scope.loaded = ->
|
||||
Enterprise.loaded && EnterpriseFee.loaded
|
||||
Enterprise.loaded && EnterpriseFee.loaded && OrderCycle.loaded
|
||||
|
||||
$scope.removeDistributionOfVariant = angular.noop
|
||||
|
||||
@@ -41,6 +41,7 @@ angular.module('admin.orderCycles').controller "AdminSimpleCreateOrderCycleCtrl"
|
||||
$scope.enterpriseFeesForEnterprise = (enterprise_id) ->
|
||||
EnterpriseFee.forEnterprise(parseInt(enterprise_id))
|
||||
|
||||
$scope.submit = (destination) ->
|
||||
$scope.submit = ($event, destination) ->
|
||||
$event.preventDefault()
|
||||
OrderCycle.mirrorIncomingToOutgoingProducts()
|
||||
OrderCycle.create(destination)
|
||||
|
||||
@@ -9,6 +9,9 @@ angular.module('admin.orderCycles').controller "AdminSimpleEditOrderCycleCtrl",
|
||||
$scope.order_cycle = OrderCycle.load $scope.orderCycleId(), (order_cycle) =>
|
||||
$scope.init()
|
||||
|
||||
$scope.$watch 'order_cycle_form.$dirty', (newValue) ->
|
||||
StatusMessage.display 'notice', 'You have unsaved changes' if newValue
|
||||
|
||||
$scope.loaded = ->
|
||||
Enterprise.loaded && EnterpriseFee.loaded && OrderCycle.loaded
|
||||
|
||||
@@ -34,6 +37,8 @@ angular.module('admin.orderCycles').controller "AdminSimpleEditOrderCycleCtrl",
|
||||
$event.preventDefault()
|
||||
OrderCycle.removeCoordinatorFee(index)
|
||||
|
||||
$scope.submit = (destination) ->
|
||||
$scope.submit = ($event, destination) ->
|
||||
$event.preventDefault()
|
||||
StatusMessage.display 'progress', "Saving..."
|
||||
OrderCycle.mirrorIncomingToOutgoingProducts()
|
||||
OrderCycle.update(destination)
|
||||
OrderCycle.update(destination, $scope.order_cycle_form)
|
||||
|
||||
@@ -154,11 +154,12 @@ angular.module('admin.orderCycles').factory 'OrderCycle', ($resource, $window, S
|
||||
else
|
||||
console.log('Failed to create order cycle')
|
||||
|
||||
update: (destination) ->
|
||||
update: (destination, form) ->
|
||||
return unless @confirmNoDistributors()
|
||||
oc = new OrderCycleResource({order_cycle: this.dataForSubmit()})
|
||||
oc.$update {order_cycle_id: this.order_cycle.id, reloading: (if destination? then 1 else 0)}, (data) =>
|
||||
if data['success']
|
||||
form.$setPristine() if form
|
||||
if destination?
|
||||
$window.location = destination
|
||||
else
|
||||
|
||||
@@ -2,13 +2,11 @@ angular.module("admin.orders").controller "ordersCtrl", ($scope, $compile, $attr
|
||||
$scope.$compile = $compile
|
||||
$scope.shops = shops
|
||||
$scope.orderCycles = orderCycles
|
||||
for oc in $scope.orderCycles
|
||||
oc.name_and_status = "#{oc.name} (#{oc.status})"
|
||||
|
||||
$scope.distributor_id = $attrs.ofnDistributorId
|
||||
$scope.order_cycle_id = $attrs.ofnOrderCycleId
|
||||
$scope.distributor_id = parseInt($attrs.ofnDistributorId)
|
||||
$scope.order_cycle_id = parseInt($attrs.ofnOrderCycleId)
|
||||
|
||||
$scope.validOrderCycle = (oc, index, array) ->
|
||||
$scope.validOrderCycle = (oc) ->
|
||||
$scope.orderCycleHasDistributor oc, parseInt($scope.distributor_id)
|
||||
|
||||
$scope.distributorHasOrderCycles = (distributor) ->
|
||||
@@ -20,3 +18,9 @@ angular.module("admin.orders").controller "ordersCtrl", ($scope, $compile, $attr
|
||||
|
||||
$scope.distributionChosen = ->
|
||||
$scope.distributor_id && $scope.order_cycle_id
|
||||
|
||||
for oc in $scope.orderCycles
|
||||
oc.name_and_status = "#{oc.name} (#{oc.status})"
|
||||
|
||||
for shop in $scope.shops
|
||||
shop.disabled = !$scope.distributorHasOrderCycles(shop)
|
||||
|
||||
@@ -1 +1 @@
|
||||
angular.module("admin.orders", ['ngResource'])
|
||||
angular.module("admin.orders", ['admin.indexUtils', 'ngResource'])
|
||||
|
||||
@@ -1,2 +1,10 @@
|
||||
angular.module("admin.shippingMethods").controller "shippingMethodCtrl", ($scope, shippingMethod) ->
|
||||
angular.module("admin.shippingMethods").controller "shippingMethodCtrl", ($scope, shippingMethod, TagRuleResource, $q) ->
|
||||
$scope.shippingMethod = shippingMethod
|
||||
|
||||
$scope.findTags = (query) ->
|
||||
defer = $q.defer()
|
||||
TagRuleResource.mapByTag (data) =>
|
||||
filtered = data.filter (tag) ->
|
||||
tag.text.toLowerCase().indexOf(query.toLowerCase()) != -1
|
||||
defer.resolve filtered
|
||||
defer.promise
|
||||
|
||||
@@ -1 +1 @@
|
||||
angular.module("admin.shippingMethods", ["ngTagsInput", 'admin.utils'])
|
||||
angular.module("admin.shippingMethods", ["ngTagsInput", 'admin.utils', 'admin.tagRules', 'templates'])
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
angular.module("admin.tagRules").factory 'TagRuleResource', ($resource) ->
|
||||
$resource('/admin/tag_rules/:action.json', {}, {
|
||||
'mapByTag':
|
||||
method: 'GET'
|
||||
isArray: true
|
||||
cache: true
|
||||
params:
|
||||
action: 'map_by_tag'
|
||||
enterprise_id: '@enterprise_id'
|
||||
})
|
||||
@@ -1 +1 @@
|
||||
angular.module("admin.tagRules", ['ngTagsInput'])
|
||||
angular.module("admin.tagRules", ['ngResource', 'ngTagsInput'])
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
angular.module("admin.utils").directive "saveBar", (StatusMessage) ->
|
||||
restrict: "E"
|
||||
transclude: true
|
||||
scope:
|
||||
save: "&"
|
||||
form: "="
|
||||
dirty: "="
|
||||
persist: "=?"
|
||||
templateUrl: "admin/save_bar.html"
|
||||
link: (scope, element, attrs) ->
|
||||
scope.StatusMessage = StatusMessage
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
angular.module("admin.utils").directive "tagsWithTranslation", ($timeout) ->
|
||||
restrict: "E"
|
||||
template: "<tags-input ng-model='object[tagsAttr]'>"
|
||||
templateUrl: "admin/tags_input.html"
|
||||
scope:
|
||||
object: "="
|
||||
tagsAttr: "@?"
|
||||
tagListAttr: "@?"
|
||||
findTags: "&"
|
||||
link: (scope, element, attrs) ->
|
||||
$timeout ->
|
||||
scope.tagsAttr ||= "tags"
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
angular.module("admin.utils").filter "translate", ->
|
||||
(key, options) ->
|
||||
t(key, options)
|
||||
|
||||
angular.module("admin.utils").filter "t", ->
|
||||
(key, options) ->
|
||||
t(key, options)
|
||||
@@ -19,19 +19,10 @@ angular.module("admin.variantOverrides").controller "AdminVariantOverridesCtrl",
|
||||
hidden: { name: "Hidden Products", visible: false }
|
||||
new: { name: "New Products", visible: false }
|
||||
|
||||
$scope.columns = Columns.setColumns
|
||||
producer: { name: "Producer", visible: true }
|
||||
product: { name: "Product", visible: true }
|
||||
sku: { name: "SKU", visible: false }
|
||||
price: { name: "Price", visible: true }
|
||||
on_hand: { name: "On Hand", visible: true }
|
||||
on_demand: { name: "On Demand", visible: false }
|
||||
reset: { name: "Reset Stock Level", visible: false }
|
||||
inheritance: { name: "Inheritance", visible: false }
|
||||
visibility: { name: "Hide", visible: false }
|
||||
|
||||
$scope.bulkActions = [ name: "Reset Stock Levels To Defaults", callback: 'resetStock' ]
|
||||
|
||||
$scope.columns = Columns.columns
|
||||
|
||||
$scope.resetSelectFilters = ->
|
||||
$scope.producerFilter = 0
|
||||
$scope.query = ''
|
||||
|
||||
@@ -1 +1 @@
|
||||
angular.module("admin.variantOverrides", ["pasvaz.bindonce", "admin.indexUtils", "admin.utils", "admin.dropdown", "admin.inventoryItems"])
|
||||
angular.module("admin.variantOverrides", ["admin.indexUtils", "admin.utils", "admin.dropdown", "admin.inventoryItems"])
|
||||
|
||||
@@ -11,8 +11,7 @@
|
||||
#= require lodash.underscore.js
|
||||
#= require angular-scroll.min.js
|
||||
#= require angular-google-maps.min.js
|
||||
#= require ../shared/mm-foundation-tpls-0.2.2.min.js
|
||||
#= require ../shared/bindonce.min.js
|
||||
#= require ../shared/mm-foundation-tpls-0.8.0.min.js
|
||||
#= require ../shared/ng-infinite-scroll.min.js
|
||||
#= require ../shared/angular-local-storage.js
|
||||
#= require ../shared/angular-slideables.js
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
Darkswarm.controller "SignupCtrl", ($scope, $http, $window, $location, Redirections, AuthenticationService) ->
|
||||
$scope.path = "/signup"
|
||||
|
||||
$scope.errors =
|
||||
email: null
|
||||
password: null
|
||||
|
||||
@@ -3,5 +3,10 @@ Darkswarm.controller "AuthenticationCtrl", ($scope, AuthenticationService, Spree
|
||||
$scope.toggle = AuthenticationService.toggle
|
||||
|
||||
$scope.spree_user = SpreeUser.spree_user
|
||||
$scope.active = AuthenticationService.active
|
||||
$scope.isActive = AuthenticationService.isActive
|
||||
$scope.select = AuthenticationService.select
|
||||
|
||||
$scope.tabs =
|
||||
login: { active: $scope.isActive('/login') }
|
||||
signup: { active: $scope.isActive('/signup') }
|
||||
forgot: { active: $scope.isActive('/forgot') }
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Darkswarm.controller "GroupPageCtrl", ($scope, group_enterprises, Enterprises, MapConfiguration, OfnMap, visibleFilter) ->
|
||||
Darkswarm.controller "GroupPageCtrl", ($scope, group_enterprises, Enterprises, MapConfiguration, OfnMap, visibleFilter, Navigation) ->
|
||||
$scope.Enterprises = Enterprises
|
||||
|
||||
all_enterprises_by_id = Enterprises.enterprises_by_id
|
||||
@@ -19,4 +19,3 @@ Darkswarm.controller "GroupPageCtrl", ($scope, group_enterprises, Enterprises, M
|
||||
|
||||
$scope.map = angular.copy MapConfiguration.options
|
||||
$scope.mapMarkers = OfnMap.enterprise_markers visible_enterprises
|
||||
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
Darkswarm.controller "GroupTabsCtrl", ($scope, $controller, Navigation) ->
|
||||
angular.extend this, $controller('TabsCtrl', {$scope: $scope})
|
||||
|
||||
$scope.tabs =
|
||||
map: { active: Navigation.isActive('/map') }
|
||||
about: { active: Navigation.isActive('/about') }
|
||||
producers: { active: Navigation.isActive('/producers') }
|
||||
hubs: { active: Navigation.isActive('/hubs') }
|
||||
@@ -1,3 +1,3 @@
|
||||
Darkswarm.controller "GroupsCtrl", ($scope, Groups, $anchorScroll, $rootScope) ->
|
||||
Darkswarm.controller "GroupsCtrl", ($scope, Groups) ->
|
||||
$scope.Groups = Groups
|
||||
$scope.order = 'position'
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
Darkswarm.controller "ProductNodeCtrl", ($scope, $modal) ->
|
||||
Darkswarm.controller "ProductNodeCtrl", ($scope, $modal, FilterSelectorsService) ->
|
||||
$scope.enterprise = $scope.product.supplier # For the modal, so it's consistent
|
||||
|
||||
$scope.triggerProductModal = ->
|
||||
$scope.productTaxonSelectors = FilterSelectorsService.createSelectors()
|
||||
$scope.productPropertySelectors = FilterSelectorsService.createSelectors()
|
||||
$modal.open(templateUrl: "product_modal.html", scope: $scope)
|
||||
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
Darkswarm.controller "ShoppingTabsCtrl", ($scope, $controller, Navigation) ->
|
||||
angular.extend this, $controller('TabsCtrl', {$scope: $scope})
|
||||
|
||||
$scope.tabs =
|
||||
about: { active: Navigation.isActive('/about') }
|
||||
producers: { active: Navigation.isActive('/producers') }
|
||||
contact: { active: Navigation.isActive('/contact') }
|
||||
groups: { active: Navigation.isActive('/groups') }
|
||||
@@ -1,15 +1,6 @@
|
||||
Darkswarm.controller "TabsCtrl", ($scope, $rootScope, $location) ->
|
||||
# Return active if supplied path matches url hash path.
|
||||
$scope.active = (path)->
|
||||
$location.hash() == path
|
||||
Darkswarm.controller "TabsCtrl", ($scope, Navigation) ->
|
||||
$scope.isActive = Navigation.isActive
|
||||
|
||||
# Select tab by setting the url hash path.
|
||||
$scope.select = (path)->
|
||||
$location.hash path
|
||||
|
||||
# Toggle tab selected status by setting the url hash path.
|
||||
$scope.toggle = (path)->
|
||||
if $scope.active(path)
|
||||
$location.hash ""
|
||||
else
|
||||
$location.hash path
|
||||
$scope.select = (path) ->
|
||||
Navigation.navigate path
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
window.Darkswarm = angular.module("Darkswarm", ["ngResource",
|
||||
'mm.foundation',
|
||||
'angularLocalStorage',
|
||||
'pasvaz.bindonce',
|
||||
'infinite-scroll',
|
||||
'angular-flash.service',
|
||||
'templates',
|
||||
|
||||
@@ -7,6 +7,22 @@ Darkswarm.directive 'mapSearch', ($timeout)->
|
||||
link: (scope, elem, attrs, ctrl)->
|
||||
$timeout =>
|
||||
map = ctrl.getMap()
|
||||
|
||||
# Use OSM tiles server
|
||||
map.mapTypes.set 'OSM', new (google.maps.ImageMapType)(
|
||||
getTileUrl: (coord, zoom) ->
|
||||
# "Wrap" x (logitude) at 180th meridian properly
|
||||
# NB: Don't touch coord.x because coord param is by reference, and changing its x property breakes something in Google's lib
|
||||
tilesPerGlobe = 1 << zoom
|
||||
x = coord.x % tilesPerGlobe
|
||||
if x < 0
|
||||
x = tilesPerGlobe + x
|
||||
# Wrap y (latitude) in a like manner if you want to enable vertical infinite scroll
|
||||
'http://tile.openstreetmap.org/' + zoom + '/' + x + '/' + coord.y + '.png'
|
||||
tileSize: new (google.maps.Size)(256, 256)
|
||||
name: 'OpenStreetMap'
|
||||
maxZoom: 18)
|
||||
|
||||
input = (document.getElementById("pac-input"))
|
||||
map.controls[google.maps.ControlPosition.TOP_LEFT].push input
|
||||
searchBox = new google.maps.places.SearchBox((input))
|
||||
@@ -21,7 +37,7 @@ Darkswarm.directive 'mapSearch', ($timeout)->
|
||||
#map.setCenter place.geometry.location
|
||||
map.fitBounds place.geometry.viewport
|
||||
#map.fitBounds bounds
|
||||
|
||||
|
||||
# Bias the SearchBox results towards places that are within the bounds of the
|
||||
# current map's viewport.
|
||||
google.maps.event.addListener map, "bounds_changed", ->
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
Darkswarm.directive "ofnOnHand", ->
|
||||
restrict: 'A'
|
||||
require: "ngModel"
|
||||
|
||||
link: (scope, elem, attr, ngModel) ->
|
||||
# In cases where this field gets its value from the HTML element rather than the model,
|
||||
# initialise the model with the HTML value.
|
||||
if scope.$eval(attr.ngModel) == undefined
|
||||
ngModel.$setViewValue elem.val()
|
||||
|
||||
ngModel.$parsers.push (viewValue) ->
|
||||
on_hand = parseInt(attr.ofnOnHand)
|
||||
if parseInt(viewValue) > on_hand
|
||||
alert t('insufficient_stock', {on_hand: on_hand})
|
||||
viewValue = on_hand
|
||||
ngModel.$setViewValue viewValue
|
||||
ngModel.$render()
|
||||
|
||||
viewValue
|
||||
@@ -22,7 +22,7 @@ Darkswarm.factory "AuthenticationService", (Navigation, $modal, $location, Redir
|
||||
@selectedPath = path
|
||||
Navigation.navigate @selectedPath
|
||||
|
||||
active: Navigation.active
|
||||
isActive: Navigation.isActive
|
||||
|
||||
close: ->
|
||||
if location.pathname in ["/", "/checkout"]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Darkswarm.factory 'Cart', (CurrentOrder, Variants, $timeout, $http, storage)->
|
||||
Darkswarm.factory 'Cart', (CurrentOrder, Variants, $timeout, $http, $modal, $rootScope, storage)->
|
||||
# Handles syncing of current cart/order state to server
|
||||
new class Cart
|
||||
dirty: false
|
||||
@@ -28,15 +28,39 @@ Darkswarm.factory 'Cart', (CurrentOrder, Variants, $timeout, $http, storage)->
|
||||
|
||||
update: =>
|
||||
@update_running = true
|
||||
|
||||
$http.post('/orders/populate', @data()).success (data, status)=>
|
||||
@saved()
|
||||
@update_running = false
|
||||
|
||||
@compareAndNotifyStockLevels data.stock_levels
|
||||
|
||||
@popQueue() if @update_enqueued
|
||||
|
||||
.error (response, status)=>
|
||||
@scheduleRetry(status)
|
||||
@update_running = false
|
||||
|
||||
compareAndNotifyStockLevels: (stockLevels) =>
|
||||
scope = $rootScope.$new(true)
|
||||
scope.variants = []
|
||||
|
||||
# TODO: These changes to quantity/max_quantity trigger another cart update, which
|
||||
# is unnecessary.
|
||||
|
||||
for li in @line_items_present()
|
||||
if stockLevels[li.variant.id]?
|
||||
li.variant.count_on_hand = stockLevels[li.variant.id].on_hand
|
||||
if li.quantity > li.variant.count_on_hand
|
||||
li.quantity = li.variant.count_on_hand
|
||||
scope.variants.push li.variant
|
||||
if li.variant.count_on_hand == 0 && li.max_quantity > li.variant.count_on_hand
|
||||
li.max_quantity = li.variant.count_on_hand
|
||||
scope.variants.push(li.variant) unless li.variant in scope.variants
|
||||
|
||||
if scope.variants.length > 0
|
||||
$modal.open(templateUrl: "out_of_stock.html", scope: scope, windowClass: 'out-of-stock-modal')
|
||||
|
||||
popQueue: =>
|
||||
@update_enqueued = false
|
||||
@scheduleUpdate()
|
||||
|
||||
@@ -10,9 +10,12 @@ Darkswarm.factory 'Checkout', (CurrentOrder, ShippingMethods, PaymentMethods, $h
|
||||
$http.put('/checkout', {order: @preprocess()}).success (data, status)=>
|
||||
Navigation.go data.path
|
||||
.error (response, status)=>
|
||||
Loading.clear()
|
||||
@errors = response.errors
|
||||
RailsFlashLoader.loadFlash(response.flash)
|
||||
if response.path
|
||||
Navigation.go response.path
|
||||
else
|
||||
Loading.clear()
|
||||
@errors = response.errors
|
||||
RailsFlashLoader.loadFlash(response.flash)
|
||||
|
||||
# Rails wants our Spree::Address data to be provided with _attributes
|
||||
preprocess: ->
|
||||
|
||||
@@ -2,6 +2,7 @@ Darkswarm.factory "EnterpriseRegistrationService", ($http, RegistrationService,
|
||||
new class EnterpriseRegistrationService
|
||||
enterprise:
|
||||
user_ids: [CurrentUser.id]
|
||||
email: CurrentUser.email
|
||||
email_address: CurrentUser.email
|
||||
address: {}
|
||||
country: availableCountries[0]
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
Darkswarm.factory "MapConfiguration", ->
|
||||
new class MapConfiguration
|
||||
options:
|
||||
center:
|
||||
center:
|
||||
latitude: -37.4713077
|
||||
longitude: 144.7851531
|
||||
zoom: 12
|
||||
additional_options: {}
|
||||
#mapTypeId: 'satellite'
|
||||
additional_options:
|
||||
# mapTypeId: 'satellite'
|
||||
mapTypeId: 'OSM'
|
||||
mapTypeControl: false
|
||||
streetViewControl: false
|
||||
styles: [{"featureType":"landscape","stylers":[{"saturation":-100},{"lightness":65},{"visibility":"on"}]},{"featureType":"poi","stylers":[{"saturation":-100},{"lightness":51},{"visibility":"simplified"}]},{"featureType":"road.highway","stylers":[{"saturation":-100},{"visibility":"simplified"}]},{"featureType":"road.arterial","stylers":[{"saturation":-100},{"lightness":30},{"visibility":"on"}]},{"featureType":"road.local","stylers":[{"saturation":-100},{"lightness":40},{"visibility":"on"}]},{"featureType":"transit","stylers":[{"saturation":-100},{"visibility":"simplified"}]},{"featureType":"administrative.province","stylers":[{"visibility":"off"}]},{"featureType":"water","elementType":"labels","stylers":[{"visibility":"on"},{"lightness":-25},{"saturation":-100}]},{"featureType":"water","elementType":"geometry","stylers":[{"hue":"#ffff00"},{"lightness":-25},{"saturation":-97}]},{"featureType":"road","elementType": "labels.icon","stylers":[{"visibility":"off"}]}]
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
Darkswarm.factory 'Navigation', ($location, $window) ->
|
||||
new class Navigation
|
||||
path: null
|
||||
path: null
|
||||
|
||||
active: (path)->
|
||||
$location.path() == path
|
||||
isActive: (path)->
|
||||
$location.path() == path
|
||||
|
||||
navigate: (path)=>
|
||||
@path = path
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
!function(){"use strict";var e=angular.module("pasvaz.bindonce",[]);e.directive("bindonce",function(){var e=function(e){if(e&&0!==e.length){var t=angular.lowercase(""+e);e=!("f"===t||"0"===t||"false"===t||"no"===t||"n"===t||"[]"===t)}else e=!1;return e},t=parseInt((/msie (\d+)/.exec(angular.lowercase(navigator.userAgent))||[])[1],10);isNaN(t)&&(t=parseInt((/trident\/.*; rv:(\d+)/.exec(angular.lowercase(navigator.userAgent))||[])[1],10));var r={restrict:"AM",controller:["$scope","$element","$attrs","$interpolate",function(r,a,i,n){var c=function(t,r,a){var i="show"===r?"":"none",n="hide"===r?"":"none";t.css("display",e(a)?i:n)},o=function(e,t){if(angular.isObject(t)&&!angular.isArray(t)){var r=[];angular.forEach(t,function(e,t){e&&r.push(t)}),t=r}t&&e.addClass(angular.isArray(t)?t.join(" "):t)},s=function(e,t){e.transclude(t,function(t){var r=e.element.parent(),a=e.element&&e.element[e.element.length-1],i=r&&r[0]||a&&a.parentNode,n=a&&a.nextSibling||null;angular.forEach(t,function(e){i.insertBefore(e,n)})})},l={watcherRemover:void 0,binders:[],group:i.boName,element:a,ran:!1,addBinder:function(e){this.binders.push(e),this.ran&&this.runBinders()},setupWatcher:function(e){var t=this;this.watcherRemover=r.$watch(e,function(e){void 0!==e&&(t.removeWatcher(),t.checkBindonce(e))},!0)},checkBindonce:function(e){var t=this,r=e.$promise?e.$promise.then:e.then;"function"==typeof r?r(function(){t.runBinders()}):t.runBinders()},removeWatcher:function(){void 0!==this.watcherRemover&&(this.watcherRemover(),this.watcherRemover=void 0)},runBinders:function(){for(;this.binders.length>0;){var r=this.binders.shift();if(!this.group||this.group==r.group){var a=r.scope.$eval(r.interpolate?n(r.value):r.value);switch(r.attr){case"boIf":e(a)&&s(r,r.scope.$new());break;case"boSwitch":var i,l=r.controller[0];(i=l.cases["!"+a]||l.cases["?"])&&(r.scope.$eval(r.attrs.change),angular.forEach(i,function(e){s(e,r.scope.$new())}));break;case"boSwitchWhen":var u=r.controller[0];u.cases["!"+r.attrs.boSwitchWhen]=u.cases["!"+r.attrs.boSwitchWhen]||[],u.cases["!"+r.attrs.boSwitchWhen].push({transclude:r.transclude,element:r.element});break;case"boSwitchDefault":var u=r.controller[0];u.cases["?"]=u.cases["?"]||[],u.cases["?"].push({transclude:r.transclude,element:r.element});break;case"hide":case"show":c(r.element,r.attr,a);break;case"class":o(r.element,a);break;case"text":r.element.text(a);break;case"html":r.element.html(a);break;case"style":r.element.css(a);break;case"src":r.element.attr(r.attr,a),t&&r.element.prop("src",a);break;case"attr":angular.forEach(r.attrs,function(e,t){var a,i;t.match(/^boAttr./)&&r.attrs[t]&&(a=t.replace(/^boAttr/,"").replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase(),i=r.scope.$eval(r.attrs[t]),r.element.attr(a,i))});break;case"href":case"alt":case"title":case"id":case"value":r.element.attr(r.attr,a)}}}this.ran=!0}};return l}],link:function(e,t,r,a){var i=r.bindonce&&e.$eval(r.bindonce);void 0!==i?a.checkBindonce(i):(a.setupWatcher(r.bindonce),t.bind("$destroy",a.removeWatcher))}};return r}),angular.forEach([{directiveName:"boShow",attribute:"show"},{directiveName:"boHide",attribute:"hide"},{directiveName:"boClass",attribute:"class"},{directiveName:"boText",attribute:"text"},{directiveName:"boBind",attribute:"text"},{directiveName:"boHtml",attribute:"html"},{directiveName:"boSrcI",attribute:"src",interpolate:!0},{directiveName:"boSrc",attribute:"src"},{directiveName:"boHrefI",attribute:"href",interpolate:!0},{directiveName:"boHref",attribute:"href"},{directiveName:"boAlt",attribute:"alt"},{directiveName:"boTitle",attribute:"title"},{directiveName:"boId",attribute:"id"},{directiveName:"boStyle",attribute:"style"},{directiveName:"boValue",attribute:"value"},{directiveName:"boAttr",attribute:"attr"},{directiveName:"boIf",transclude:"element",terminal:!0,priority:1e3},{directiveName:"boSwitch",require:"boSwitch",controller:function(){this.cases={}}},{directiveName:"boSwitchWhen",transclude:"element",priority:800,require:"^boSwitch"},{directiveName:"boSwitchDefault",transclude:"element",priority:800,require:"^boSwitch"}],function(t){var r=200;return e.directive(t.directiveName,function(){var e={priority:t.priority||r,transclude:t.transclude||!1,terminal:t.terminal||!1,require:["^bindonce"].concat(t.require||[]),controller:t.controller,compile:function(e,r,a){return function(e,r,i,n){var c=n[0],o=i.boParent;if(o&&c.group!==o){var s=c.element.parent();c=void 0;for(var l;9!==s[0].nodeType&&s.length;){if((l=s.data("$bindonceController"))&&l.group===o){c=l;break}s=s.parent()}if(!c)throw new Error("No bindonce controller: "+o)}c.addBinder({element:r,attr:t.attribute||t.directiveName,attrs:i,value:i[t.directiveName],interpolate:t.interpolate,group:o,transclude:a,controller:n.slice(1),scope:e})}}};return e})})}();
|
||||
File diff suppressed because one or more lines are too long
10
app/assets/javascripts/shared/mm-foundation-tpls-0.8.0.min.js
vendored
Normal file
10
app/assets/javascripts/shared/mm-foundation-tpls-0.8.0.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,11 @@
|
||||
.ofn-drop-down.right#columns-dropdown{ ng: { controller: 'ColumnsDropdownCtrl' } }
|
||||
%span{ :class => 'icon-reorder' }= " #{t('admin.columns')}".html_safe
|
||||
%span{ 'ng-class' => "expanded && 'icon-caret-up' || !expanded && 'icon-caret-down'" }
|
||||
%div.menu{ 'ng-show' => "expanded" }
|
||||
%div.menu_item{ ng: { repeat: "column in columns", click: "toggle(column)", class: "{selected: column.visible}" } }
|
||||
%span.check
|
||||
%span.name {{column.name }}
|
||||
%hr
|
||||
%div.menu_item.text-center
|
||||
%input.fullwidth.orange{ type: "button", ng: { value: "saved() ? 'Saved': 'Saving'", show: "saved() || saving", disabled: "saved()" } }
|
||||
%input.fullwidth.red{ type: "button", value: 'Save As Default', ng: { show: "!saved() && !saving", click: "saveColumnPreferences(action)"} }
|
||||
@@ -0,0 +1,15 @@
|
||||
#new-customer-dialog
|
||||
.text-normal.margin-bottom-30.text-center
|
||||
= t('admin.customers.index.add_a_new_customer_for', shop_name: "{{ CurrentShop.shop.name }}:")
|
||||
|
||||
%form{ name: 'new_customer_form', novalidate: true }
|
||||
|
||||
.text-center.margin-bottom-30
|
||||
%input.fullwidth{ type: 'email', name: 'email', required: true, placeholder: t('admin.customers.index.customer_placeholder'), ng: { model: "email" } }
|
||||
%div{ ng: { show: "email == submitted" } }
|
||||
.error{ ng: { show: "(new_customer_form.email.$error.email || new_customer_form.email.$error.required)" } }
|
||||
= t('admin.customers.index.valid_email_error')
|
||||
.error{ ng: { repeat: "error in errors", bind: "error" } }
|
||||
|
||||
.text-center
|
||||
%input.button.red.icon-plus{ type: 'submit', value: t('admin.customers.index.add_customer'), ng: { click: 'addCustomer(new_customer_form.email.$valid)' } }
|
||||
@@ -17,13 +17,13 @@
|
||||
%td.severity
|
||||
%i.icon-warning-sign.issue
|
||||
%td.description
|
||||
%span{ bo: { bind: "issue.description" } }
|
||||
%span{ ng: { bind: "::issue.description" } }
|
||||
%td.resolve
|
||||
%div{ ng: { bind: { html: "issue.link" } } }
|
||||
%tr{ ng: { repeat: "warning in warnings"} }
|
||||
%td.severity
|
||||
%i.icon-warning-sign.warning
|
||||
%td.description
|
||||
%span{ bo: { bind: "warning.description" } }
|
||||
%span{ ng: { bind: "::warning.description" } }
|
||||
%td.resolve
|
||||
%div{ ng: { bind: { html: "warning.link" } } }
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#save-bar.animate-show{ ng: { show: 'form.$dirty || StatusMessage.active()' } }
|
||||
.twelve.columns.alpha
|
||||
%h5#status-message{ ng: { style: 'StatusMessage.statusMessage.style' } }
|
||||
{{ StatusMessage.statusMessage.text || " " }}
|
||||
.four.columns.omega.text-right
|
||||
%input.red{type: "button", value: "Save Changes", ng: { disabled: '!form.$dirty', click: "save()" } }
|
||||
#save-bar.animate-show{ ng: { show: 'dirty || persist || StatusMessage.active()' } }
|
||||
.container
|
||||
.eight.columns.alpha
|
||||
%h5#status-message{ ng: { style: 'StatusMessage.statusMessage.style' } }
|
||||
{{ StatusMessage.statusMessage.text || " " }}
|
||||
.eight.columns.omega.text-right{ ng: { transclude: true } }
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
%div{ ng: { show: "data.length > limit" } }
|
||||
%input{ type: 'button', value: 'Show More', ng: { click: 'limit = limit + increment' } }
|
||||
or
|
||||
%input{ type: 'button', value: "Show All ({{ data.length - limit }} More)", ng: { click: 'limit = data.length' } }
|
||||
8
app/assets/javascripts/templates/admin/tag.html.haml
Normal file
8
app/assets/javascripts/templates/admin/tag.html.haml
Normal file
@@ -0,0 +1,8 @@
|
||||
.tag-template
|
||||
%div
|
||||
%span.tag-with-rules{ ng: { if: "data.rules" }, "ofn-with-tip" => "{{ 'admin.tag_has_rules' | t:{num: data.rules} }}" }
|
||||
{{$getDisplayText()}}
|
||||
%span{ ng: { if: "!data.rules" } }
|
||||
{{$getDisplayText()}}
|
||||
%a.remove-button{ ng: {click: "$removeTag()"} }
|
||||
✖
|
||||
@@ -0,0 +1,11 @@
|
||||
.autocomplete-template
|
||||
%span.tag-with-rules{ ng: { if: "data.rules" } }
|
||||
{{$getDisplayText()}}
|
||||
%span.tag-with-rules{ ng: { if: "data.rules == 1" } }
|
||||
—
|
||||
= t 'admin.has_one_rule'
|
||||
%span.tag-with-rules{ ng: { if: "data.rules > 1" } }
|
||||
—
|
||||
= t 'admin.has_n_rules', { num: '{{data.rules}}' }
|
||||
%span{ ng: { if: "!data.rules" } }
|
||||
{{$getDisplayText()}}
|
||||
@@ -0,0 +1,7 @@
|
||||
%tags-input{ template: 'admin/tag.html', ng: { model: 'object[tagsAttr]' } }
|
||||
%auto-complete{source: "findTags({query: $query})",
|
||||
template: "admin/tag_autocomplete.html",
|
||||
"min-length" => "0",
|
||||
"load-on-focus" => "true",
|
||||
"load-on-empty" => "true",
|
||||
"max-results-to-show" => "32"}
|
||||
@@ -1,4 +1,4 @@
|
||||
%ul{ bindonce: true }
|
||||
%ul
|
||||
%active-selector{ ng: { repeat: "selector in allSelectors", show: "ifDefined(selector.fits, true)" } }
|
||||
%render-svg{path: "{{selector.object.icon}}", ng: { if: "selector.object.icon"} }
|
||||
%span{"bo-text" => "selector.object.name"}
|
||||
%span{"ng-bind" => "::selector.object.name"}
|
||||
|
||||
@@ -1,10 +1,5 @@
|
||||
%tab#forgot{"ng-controller" => "ForgotCtrl",
|
||||
heading: "{{'forgot_password' | t}}",
|
||||
active: "active(path)",
|
||||
select: "select(path)"}
|
||||
|
||||
%form{"ng-submit" => "submit()"}
|
||||
|
||||
%tab#forgot{ heading: "{{'forgot_password' | t}}", active: "tabs.forgot.active", select: "select(path)"}
|
||||
%form{ ng: { controller: "ForgotCtrl", submit: "submit()" } }
|
||||
.row
|
||||
.large-12.columns
|
||||
.alert-box.success.radius{"ng-show" => "sent"}
|
||||
@@ -13,18 +8,18 @@
|
||||
%div{"ng-show" => "!sent"}
|
||||
.alert-box.alert{"ng-show" => "errors != null"}
|
||||
{{ errors }}
|
||||
|
||||
|
||||
.row
|
||||
.large-12.columns
|
||||
%label{for: "email"} {{'signup_email' | t}}
|
||||
%input.title.input-text{name: "email",
|
||||
%input.title.input-text{name: "email",
|
||||
type: "email",
|
||||
id: "email",
|
||||
tabindex: 1,
|
||||
"ng-model" => "spree_user.email"}
|
||||
.row
|
||||
.large-12.columns
|
||||
%input.button.primary{name: "commit",
|
||||
tabindex: "3",
|
||||
type: "submit",
|
||||
%input.button.primary{name: "commit",
|
||||
tabindex: "3",
|
||||
type: "submit",
|
||||
value: "{{'reset_password' | t}}"}
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
%tab#login-content{"ng-controller" => "LoginCtrl",
|
||||
heading: "{{'label_login' | t}}",
|
||||
active: "active(path)",
|
||||
select: "select(path)"}
|
||||
%form{"ng-submit" => "submit()"}
|
||||
%tab#login-content{ heading: "{{'label_login' | t}}", active: "tabs.login.active", select: "select(path)"}
|
||||
%form{ ng: { controller: "LoginCtrl", submit: "submit()" } }
|
||||
.row
|
||||
.large-12.columns
|
||||
.alert-box.alert{"ng-show" => "errors != null"}
|
||||
@@ -10,7 +7,7 @@
|
||||
.row
|
||||
.large-12.columns
|
||||
%label{for: "email"} {{'email' | t}}
|
||||
%input.title.input-text{name: "email",
|
||||
%input.title.input-text{name: "email",
|
||||
type: "email",
|
||||
id: "email",
|
||||
tabindex: 1,
|
||||
@@ -18,7 +15,7 @@
|
||||
.row
|
||||
.large-12.columns
|
||||
%label{for: "password"} {{'password' | t}}
|
||||
%input.title.input-text{name: "password",
|
||||
%input.title.input-text{name: "password",
|
||||
type: "password",
|
||||
id: "password",
|
||||
autocomplete: "off",
|
||||
@@ -26,15 +23,15 @@
|
||||
"ng-model" => "spree_user.password"}
|
||||
.row
|
||||
.large-12.columns
|
||||
%input{name: "remember_me",
|
||||
type: "checkbox",
|
||||
id: "remember_me",
|
||||
%input{name: "remember_me",
|
||||
type: "checkbox",
|
||||
id: "remember_me",
|
||||
value: "1",
|
||||
"ng-model" => "spree_user.remember_me"}
|
||||
%label{for: "remember_me"} {{'remember_me' | t}}
|
||||
.row
|
||||
.large-12.columns
|
||||
%input.button.primary{name: "commit",
|
||||
tabindex: "3",
|
||||
type: "submit",
|
||||
%input.button.primary{name: "commit",
|
||||
tabindex: "3",
|
||||
type: "submit",
|
||||
value: "{{'label_login' | t}}"}
|
||||
|
||||
13
app/assets/javascripts/templates/out_of_stock.html.haml
Normal file
13
app/assets/javascripts/templates/out_of_stock.html.haml
Normal file
@@ -0,0 +1,13 @@
|
||||
%a.close-reveal-modal{"ng-click" => "$close()"}
|
||||
%i.ofn-i_009-close
|
||||
|
||||
%h3 Reduced stock available
|
||||
|
||||
%p While you've been shopping, the stock levels for one or more of the products in your cart have reduced. Here's what's changed:
|
||||
|
||||
%p{'ng-repeat' => "v in variants"}
|
||||
%em {{ v.name_to_display }} - {{ v.unit_to_display }}
|
||||
%span{'ng-if' => "v.count_on_hand == 0"}
|
||||
is now out of stock.
|
||||
%span{'ng-if' => "v.count_on_hand > 0"}
|
||||
now only has {{ v.count_on_hand }} remaining.
|
||||
@@ -1,11 +1,11 @@
|
||||
%div.contact-container{bindonce: true}
|
||||
%div.modal-centered{"bo-if" => "enterprise.email_address || enterprise.website || enterprise.phone"}
|
||||
%div.contact-container
|
||||
%div.modal-centered{"ng-if" => "::enterprise.email_address || enterprise.website || enterprise.phone"}
|
||||
%p.modal-header {{'contact' | t}}
|
||||
%p{"bo-if" => "enterprise.phone", "bo-text" => "enterprise.phone"}
|
||||
%p{"ng-if" => "::enterprise.phone", "ng-bind" => "::enterprise.phone"}
|
||||
|
||||
%p.word-wrap{"ng-if" => "enterprise.email_address"}
|
||||
%a{"bo-href" => "enterprise.email_address | stripUrl", target: "_blank", mailto: true}
|
||||
%span.email{"bo-bind" => "enterprise.email_address | stripUrl"}
|
||||
%p.word-wrap{"ng-if" => "::enterprise.email_address"}
|
||||
%a{"ng-href" => "{{::enterprise.email_address | stripUrl}}", target: "_blank", mailto: true}
|
||||
%span.email{"ng-bind" => "::enterprise.email_address | stripUrl"}
|
||||
|
||||
%p.word-wrap{"ng-if" => "enterprise.website"}
|
||||
%a{"bo-href-i" => "http://{{enterprise.website | stripUrl}}", target: "_blank", "bo-bind" => "enterprise.website | stripUrl"}
|
||||
%a{"ng-href" => "http://{{::enterprise.website | stripUrl}}", target: "_blank", "ng-bind" => "::enterprise.website | stripUrl"}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.row{bindonce: true}
|
||||
.row
|
||||
.small-12.large-8.columns
|
||||
/ TODO: Rob add logic for taxons and properties too:
|
||||
/ %div{"ng-if" => "enterprise.long_description.length > 0 || enterprise.logo"}
|
||||
@@ -22,8 +22,8 @@
|
||||
-# / TODO: Rob - need popover, use will's directive or this? http://pineconellc.github.io/angular-foundation/
|
||||
-#
|
||||
.about-container.pad-top
|
||||
%img.enterprise-logo{"bo-src" => "enterprise.logo", "bo-if" => "enterprise.logo"}
|
||||
%p.text-small{"ng-bind-html" => "enterprise.long_description"}
|
||||
%img.enterprise-logo{"ng-src" => "{{::enterprise.logo}}", "ng-if" => "::enterprise.logo"}
|
||||
%p.text-small{"ng-bind-html" => "::enterprise.long_description"}
|
||||
.small-12.large-4.columns
|
||||
%ng-include{src: "'partials/contact.html'"}
|
||||
%ng-include{src: "'partials/follow.html'"}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
.highlight{bindonce: true, "ng-class" => "{'is_distributor' : enterprise.is_distributor}"}
|
||||
.highlight{"ng-class" => "::{'is_distributor' : enterprise.is_distributor}"}
|
||||
.highlight-top.row
|
||||
.small-12.medium-7.large-8.columns
|
||||
%h3{"ng-if" => "enterprise.is_distributor"}
|
||||
%a{"bo-href" => "enterprise.path", "ofn-change-hub" => "enterprise"}
|
||||
%i{"ng-class" => "enterprise.icon_font"}
|
||||
%span{"bo-text" => "enterprise.name"}
|
||||
%h3{"ng-if" => "!enterprise.is_distributor", "ng-class" => "{'is_producer' : enterprise.is_primary_producer}"}
|
||||
%i{"ng-class" => "enterprise.icon_font"}
|
||||
%span{"bo-text" => "enterprise.name"}
|
||||
%h3{"ng-if" => "::enterprise.is_distributor"}
|
||||
%a{"ng-href" => "{{::enterprise.path}}", "ofn-change-hub" => "enterprise"}
|
||||
%i{"ng-class" => "::enterprise.icon_font"}
|
||||
%span{"ng-bind" => "::enterprise.name"}
|
||||
%h3{"ng-if" => "::!enterprise.is_distributor", "ng-class" => "::{'is_producer' : enterprise.is_primary_producer}"}
|
||||
%i{"ng-class" => "::enterprise.icon_font"}
|
||||
%span{"ng-bind" => "::enterprise.name"}
|
||||
.small-12.medium-5.large-4.columns.text-right.small-only-text-left
|
||||
%p{"bo-bind" => "[enterprise.address.city, enterprise.address.state_name] | printArray"}
|
||||
%img.hero-img{"bo-src" => "enterprise.promo_image"}
|
||||
%p{"ng-bind" => "::[enterprise.address.city, enterprise.address.state_name] | printArray"}
|
||||
%img.hero-img{"ng-src" => "{{::enterprise.promo_image}}"}
|
||||
|
||||
@@ -1,19 +1,18 @@
|
||||
%div.modal-centered{bindonce: true, "bo-if" => "enterprise.twitter || enterprise.facebook || enterprise.linkedin || enterprise.instagram"}
|
||||
%div.modal-centered{ "ng-if" => "::enterprise.twitter || enterprise.facebook || enterprise.linkedin || enterprise.instagram"}
|
||||
%p.modal-header {{'follow' | t}}
|
||||
.follow-icons
|
||||
%span{"bo-if" => "enterprise.twitter"}
|
||||
%a{"bo-href-i" => "http://twitter.com/{{enterprise.twitter}}", target: "_blank"}
|
||||
%span{"ng-if" => "::enterprise.twitter"}
|
||||
%a{"ng-href" => "http://twitter.com/{{::enterprise.twitter}}", target: "_blank"}
|
||||
%i.ofn-i_041-twitter
|
||||
|
||||
%span{"bo-if" => "enterprise.facebook"}
|
||||
%a{"bo-href-i" => "http://{{enterprise.facebook | stripUrl}}", target: "_blank"}
|
||||
%i.ofn-i_044-facebook
|
||||
|
||||
%span{"bo-if" => "enterprise.linkedin"}
|
||||
%a{"bo-href-i" => "http://{{enterprise.linkedin | stripUrl}}", target: "_blank"}
|
||||
%i.ofn-i_042-linkedin
|
||||
|
||||
%span{"bo-if" => "enterprise.instagram"}
|
||||
%a{"bo-href-i" => "http://instagram.com/{{enterprise.instagram}}", target: "_blank"}
|
||||
%i.ofn-i_043-instagram
|
||||
|
||||
%span{"ng-if" => "::enterprise.facebook"}
|
||||
%a{"ng-href" => "http://{{::enterprise.facebook | stripUrl}}", target: "_blank"}
|
||||
%i.ofn-i_044-facebook
|
||||
|
||||
%span{"ng-if" => "::enterprise.linkedin"}
|
||||
%a{"ng-href" => "http://{{::enterprise.linkedin | stripUrl}}", target: "_blank"}
|
||||
%i.ofn-i_042-linkedin
|
||||
|
||||
%span{"ng-if" => "::enterprise.instagram"}
|
||||
%a{"ng-href" => "http://instagram.com/{{::enterprise.instagram}}", target: "_blank"}
|
||||
%i.ofn-i_043-instagram
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
.row.pad-top{bindonce: true, ng: { if: 'enterprise.is_distributor' } }
|
||||
.row.pad-top{ng: { if: 'enterprise.is_distributor' } }
|
||||
.cta-container.small-12.columns
|
||||
.row
|
||||
.small-4.columns
|
||||
%label{"active-table-hub-link" => "enterprise", change: "{{'change_shop' | t}}", shop: "{{'shop_at' | t}}"}
|
||||
.small-8.columns.right
|
||||
%label.right{"bo-if" => "enterprise.pickup || enterprise.delivery"}
|
||||
%label.right{"ng-if" => "::enterprise.pickup || enterprise.delivery"}
|
||||
{{'hubs_delivery_options' | t}}:
|
||||
%span{"bo-if" => "enterprise.pickup"}
|
||||
%span{"ng-if" => "::enterprise.pickup"}
|
||||
%i.ofn-i_038-takeaway
|
||||
{{'hubs_pickup' | t}}
|
||||
%span{"bo-if" => "enterprise.delivery"}
|
||||
%span{"ng-if" => "::enterprise.delivery"}
|
||||
%i.ofn-i_039-delivery
|
||||
{{'hubs_delivery' | t}}
|
||||
.row
|
||||
.columns.small-12
|
||||
%a.cta-hub{"bo-href" => "enterprise.path",
|
||||
%a.cta-hub{"ng-href" => "{{::enterprise.path}}",
|
||||
"ng-class" => "{primary: enterprise.active, secondary: !enterprise.active}",
|
||||
"ofn-change-hub" => "enterprise"}
|
||||
%i.ofn-i_033-open-sign{"bo-if" => "enterprise.active"}
|
||||
%i.ofn-i_032-closed-sign{"bo-if" => "!enterprise.active"}
|
||||
.hub-name{"bo-text" => "enterprise.name"}
|
||||
.button-address{"bo-bind" => "[enterprise.address.city, enterprise.address.state_name] | printArray"}
|
||||
%i.ofn-i_033-open-sign{"ng-if" => "::enterprise.active"}
|
||||
%i.ofn-i_032-closed-sign{"ng-if" => "::!enterprise.active"}
|
||||
.hub-name{"ng-bind" => "::enterprise.name"}
|
||||
.button-address{"ng-bind" => "::[enterprise.address.city, enterprise.address.state_name] | printArray"}
|
||||
/ %i.ofn-i_007-caret-right
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
-# Show places to buy products from this producer, when there are any
|
||||
-# Do not show this for producer shops selling only their own produce,
|
||||
-# Since a shopping link will already have been displayed in hub_details.html.haml
|
||||
.row.active_table_row.pad-top{bindonce: true, "ng-if" => "enterprise.is_primary_producer && enterprise.hubs.length > 0 && !(enterprise.hubs.length == 1 && enterprise.hubs[0] == enterprise)"}
|
||||
.row.active_table_row.pad-top{ "ng-if" => "enterprise.is_primary_producer && enterprise.hubs.length > 0 && !(enterprise.hubs.length == 1 && enterprise.hubs[0] == enterprise)"}
|
||||
.columns.small-12
|
||||
.row
|
||||
.columns.small-12.fat
|
||||
%div{"bo-if" => "enterprise.name"}
|
||||
%label{"bo-html" => "'shop_for_products_html' | t:{enterprise: enterprise.name}"}
|
||||
%div.show-for-medium-up{"bo-if" => "!enterprise.name"}
|
||||
%div{"ng-if" => "::enterprise.name"}
|
||||
%label{"ng-html" => "::'shop_for_products_html' | t:{enterprise: enterprise.name}"}
|
||||
%div.show-for-medium-up{"ng-if" => "::!enterprise.name"}
|
||||
|
||||
.row.cta-container
|
||||
.columns.small-12
|
||||
%a.cta-hub{"ng-repeat" => "hub in enterprise.hubs | filter:{id: '!'+enterprise.id} | orderBy:'-active'",
|
||||
"bo-href" => "hub.path", "ofn-empties-cart" => "hub",
|
||||
"bo-class" => "{primary: hub.active, secondary: !hub.active}"}
|
||||
%i.ofn-i_033-open-sign{"bo-if" => "hub.active"}
|
||||
%i.ofn-i_032-closed-sign{"bo-if" => "!hub.active"}
|
||||
.hub-name{"bo-text" => "hub.name"}
|
||||
.button-address{"bo-bind" => "[hub.address.city, hub.address.state_name] | printArray"}
|
||||
"ng-href" => "{{::hub.path}}", "ofn-empties-cart" => "hub",
|
||||
"ng-class" => "::{primary: hub.active, secondary: !hub.active}"}
|
||||
%i.ofn-i_033-open-sign{"ng-if" => "::hub.active"}
|
||||
%i.ofn-i_032-closed-sign{"ng-if" => "::!hub.active"}
|
||||
.hub-name{"ng-bind" => "::hub.name"}
|
||||
.button-address{"ng-bind" => "::[hub.address.city, hub.address.state_name] | printArray"}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
.small-5.medium-3.large-3.columns.text-right{"ng-if" => "::!variant.product.group_buy"}
|
||||
|
||||
%input{type: :number,
|
||||
integer: true,
|
||||
value: nil,
|
||||
min: 0,
|
||||
placeholder: "0",
|
||||
"ofn-disable-scroll" => true,
|
||||
"ng-model" => "variant.line_item.quantity",
|
||||
"ofn-on-hand" => "{{variant.on_demand && 9999 || variant.count_on_hand }}",
|
||||
"ng-disabled" => "!variant.on_demand && variant.count_on_hand == 0",
|
||||
name: "variants[{{variant.id}}]", id: "variants_{{variant.id}}"}
|
||||
@@ -0,0 +1,23 @@
|
||||
.small-5.medium-3.large-3.columns.text-right{"ng-if" => "::variant.product.group_buy"}
|
||||
%span.bulk-input-container
|
||||
%span.bulk-input
|
||||
%input.bulk.first{type: :number,
|
||||
value: nil,
|
||||
integer: true,
|
||||
min: 0,
|
||||
"ng-model" => "variant.line_item.quantity",
|
||||
placeholder: "{{'shop_variant_quantity_min' | t}}",
|
||||
"ofn-disable-scroll" => true,
|
||||
"ofn-on-hand" => "{{variant.on_demand && 9999 || variant.count_on_hand }}",
|
||||
name: "variants[{{variant.id}}]", id: "variants_{{variant.id}}"}
|
||||
%span.bulk-input
|
||||
%input.bulk.second{type: :number,
|
||||
"ng-disabled" => "!variant.line_item.quantity",
|
||||
integer: true,
|
||||
min: 0,
|
||||
"ng-model" => "variant.line_item.max_quantity",
|
||||
placeholder: "{{'shop_variant_quantity_max' | t}}",
|
||||
"ofn-disable-scroll" => true,
|
||||
min: "{{variant.line_item.quantity}}",
|
||||
name: "variant_attributes[{{variant.id}}][max_quantity]",
|
||||
id: "variants_{{variant.id}}_max"}
|
||||
@@ -1,38 +1,37 @@
|
||||
.joyride-tip-guide.price_breakdown{bindonce: true, "ng-class" => "{ in: tt_isOpen, fade: tt_animation }"}
|
||||
.joyride-tip-guide.price_breakdown{"ng-class" => "{ in: tt_isOpen, fade: tt_animation }"}
|
||||
%span.joyride-nub.right
|
||||
.joyride-content-wrapper
|
||||
.collapsed{"ng-show" => "!expanded"}
|
||||
%price-percentage{percentage: 'variant.basePricePercentage'}
|
||||
%a{"ng-click" => "expanded = !expanded"}
|
||||
%span{"bo-text" => "'price_breakdown' | t"}
|
||||
%a{"ng-click" => "expanded = !expanded"}
|
||||
%span{"ng-bind" => "::'price_breakdown' | t"}
|
||||
%i.ofn-i_005-caret-down
|
||||
|
||||
.expanded{"ng-show" => "expanded"}
|
||||
%ul
|
||||
%li.cost
|
||||
.right {{ variant.price | localizeCurrency }}
|
||||
%span{"bo-text" => "'item_cost' | t"}
|
||||
%li.admin-fee{"bo-if" => "variant.fees.admin"}
|
||||
%span{"ng-bind" => "::'item_cost' | t"}
|
||||
%li.admin-fee{"ng-if" => "::variant.fees.admin"}
|
||||
.right {{ variant.fees.admin | localizeCurrency }}
|
||||
%span{"bo-text" => "'admin_fee' | t"}
|
||||
%li.sales-fee{"bo-if" => "variant.fees.sales"}
|
||||
%span{"ng-bind" => "::'admin_fee' | t"}
|
||||
%li.sales-fee{"ng-if" => "::variant.fees.sales"}
|
||||
.right {{ variant.fees.sales | localizeCurrency }}
|
||||
%span{"bo-text" => "'sales_fee' | t"}
|
||||
%li.packing-fee{"bo-if" => "variant.fees.packing"}
|
||||
%span{"ng-bind" => "::'sales_fee' | t"}
|
||||
%li.packing-fee{"ng-if" => "::variant.fees.packing"}
|
||||
.right {{ variant.fees.packing | localizeCurrency }}
|
||||
%span{"bo-text" => "'packing_fee' | t"}
|
||||
%li.transport-fee{"bo-if" => "variant.fees.transport"}
|
||||
%span{"ng-bind" => "::'packing_fee' | t"}
|
||||
%li.transport-fee{"ng-if" => "::variant.fees.transport"}
|
||||
.right {{ variant.fees.transport | localizeCurrency }}
|
||||
%span{"bo-text" => "'transport_fee' | t"}
|
||||
%li.fundraising-fee{"bo-if" => "variant.fees.fundraising"}
|
||||
%span{"ng-bind" => "::'transport_fee' | t"}
|
||||
%li.fundraising-fee{"ng-if" => "::variant.fees.fundraising"}
|
||||
.right {{ variant.fees.fundraising | localizeCurrency }}
|
||||
%span{"bo-text" => "'fundraising_fee' | t"}
|
||||
%span{"ng-bind" => "::'fundraising_fee' | t"}
|
||||
%li.total
|
||||
%strong
|
||||
.right = {{ variant.price_with_fees | localizeCurrency }}
|
||||
|
||||
|
||||
%a{"ng-click" => "expanded = !expanded"}
|
||||
%span{"bo-text" => "'price_graph' | t"}
|
||||
%a{"ng-click" => "expanded = !expanded"}
|
||||
%span{"ng-bind" => "::'price_graph' | t"}
|
||||
%i.ofn-i_006-caret-up
|
||||
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
.row{bindonce: true}
|
||||
.row
|
||||
|
||||
.columns.small-12.large-6.product-header
|
||||
%h3{"bo-text" => "product.name"}
|
||||
%h3{"ng-bind" => "::product.name"}
|
||||
%span
|
||||
%em {{'products_from' | t}}
|
||||
%span{"bo-text" => "enterprise.name"}
|
||||
%span{"ng-bind" => "::enterprise.name"}
|
||||
|
||||
%br
|
||||
|
||||
.filter-shopfront.taxon-selectors.inline-block
|
||||
%filter-selector{ objects: "[product] | taxonsOf" }
|
||||
%filter-selector{ 'selector-set' => "productTaxonSelectors", objects: "[product] | taxonsOf" }
|
||||
|
||||
.filter-shopfront.property-selectors.inline-block
|
||||
%filter-selector{ objects: "[product] | propertiesWithValuesOf" }
|
||||
%filter-selector{ 'selector-set' => "productPropertySelectors", objects: "[product] | propertiesWithValuesOf" }
|
||||
|
||||
%div{"ng-if" => "product.description"}
|
||||
%hr
|
||||
%p.text-small{"bo-text" => "product.description"}
|
||||
%p.text-small{"ng-bind" => "::product.description"}
|
||||
%hr
|
||||
|
||||
.columns.small-12.large-6
|
||||
%img.product-img{"bo-src" => "product.largeImage", "bo-if" => "product.largeImage"}
|
||||
%img.product-img.placeholder{"bo-src" => "'/assets/noimage/large.png'", "bo-if" => "!product.largeImage"}
|
||||
%img.product-img{"ng-src" => "{{::product.largeImage}}", "ng-if" => "::product.largeImage"}
|
||||
%img.product-img.placeholder{ src: "/assets/noimage/large.png", "ng-if" => "::!product.largeImage"}
|
||||
|
||||
%ng-include{src: "'partials/close.html'"}
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
.container#registration-details{bindonce: true}
|
||||
.container#registration-details
|
||||
%ng-include{ src: "'registration/steps.html'" }
|
||||
.row
|
||||
.small-12.columns
|
||||
%header
|
||||
%h2 {{'registration_detail_headline' | t}}
|
||||
%h5{ bo: { if: "enterprise.type != 'own'" } } {{'registration_detail_enterprise' | t}}
|
||||
%h5{ bo: { if: "enterprise.type == 'own'" } } {{'registration_detail_producer' | t}}
|
||||
%h5{ ng: { if: "::enterprise.type != 'own'" } } {{'registration_detail_enterprise' | t}}
|
||||
%h5{ ng: { if: "::enterprise.type == 'own'" } } {{'registration_detail_producer' | t}}
|
||||
|
||||
%form{ name: 'details', novalidate: true, ng: { controller: "RegistrationFormCtrl", submit: "selectIfValid('contact',details)" } }
|
||||
|
||||
.row
|
||||
.small-12.medium-9.large-12.columns.end
|
||||
.field
|
||||
%label{ for: 'enterprise_name', bo: { if: "enterprise.type != 'own'" } } {{'registration_detail_name_enterprise' | t}}
|
||||
%label{ for: 'enterprise_name', bo: { if: "enterprise.type == 'own'" } } {{'registration_detail_name_producer' | t}}
|
||||
%label{ for: 'enterprise_name', ng: { if: "::enterprise.type != 'own'" } } {{'registration_detail_name_enterprise' | t}}
|
||||
%label{ for: 'enterprise_name', ng: { if: "::enterprise.type == 'own'" } } {{'registration_detail_name_producer' | t}}
|
||||
%input.chunky{ id: 'enterprise_name', name: 'name', placeholder: "{{'registration_detail_name_placeholder' | t}}", required: true, ng: { model: 'enterprise.name' } }
|
||||
%span.error{ ng: { show: "details.name.$error.required && submitted" } }
|
||||
{{'registration_detail_name_error' | t}}
|
||||
|
||||
@@ -10,6 +10,6 @@
|
||||
.small-12.columns.text-center
|
||||
%h4{ "ng-bind" => "'registration_finished_activate' | t:{enterprise: enterprise.name}" }
|
||||
|
||||
%p{ "ng-bind-html" => "t('registration_finished_activate_instruction_html', {email: enterprise.email})"}
|
||||
%p{ "ng-bind-html" => "'registration_finished_activate_instruction_html' | t:{email: enterprise.email}"}
|
||||
|
||||
%a.button.primary{ type: "button", href: "/" } {{'registration_finished_action' | t}} >
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.container#registration-type{bindonce: true}
|
||||
.container#registration-type
|
||||
|
||||
%ng-include{ src: "'registration/steps.html'" }
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
{{'registration_type_question' | t}}
|
||||
|
||||
%form{ name: 'type', novalidate: true, ng: { controller: "RegistrationFormCtrl", submit: "create(type)" } }
|
||||
.row#enterprise-types{ 'data-equalizer' => true, bo: { if: "enterprise.type != 'own'" } }
|
||||
.row#enterprise-types{ 'data-equalizer' => true, ng: { if: "::enterprise.type != 'own'" } }
|
||||
.small-12.columns.field
|
||||
.row
|
||||
.small-12.medium-6.large-6.columns{ 'data-equalizer-watch' => true }
|
||||
|
||||
@@ -1,61 +1,26 @@
|
||||
.variants.row
|
||||
.small-12.medium-4.large-4.columns.variant-name
|
||||
.table-cell
|
||||
.table-cell
|
||||
.inline {{ variant.name_to_display }}
|
||||
.bulk-buy.inline{"bo-if" => "variant.product.group_buy"}
|
||||
.bulk-buy.inline{"ng-if" => "::variant.product.group_buy"}
|
||||
%i.ofn-i_056-bulk><
|
||||
%em><
|
||||
\ {{'bulk' | t}}
|
||||
|
||||
-# WITHOUT GROUP BUY
|
||||
.small-5.medium-3.large-3.columns.text-right{"bo-if" => "!variant.product.group_buy"}
|
||||
|
||||
%input{type: :number,
|
||||
integer: true,
|
||||
value: nil,
|
||||
min: 0,
|
||||
placeholder: "0",
|
||||
"ofn-disable-scroll" => true,
|
||||
"ng-model" => "variant.line_item.quantity",
|
||||
max: "{{variant.on_demand && 9999 || variant.count_on_hand }}",
|
||||
name: "variants[{{variant.id}}]", id: "variants_{{variant.id}}"}
|
||||
|
||||
|
||||
-# WITH GROUP BUY
|
||||
.small-5.medium-3.large-3.columns.text-right{"bo-if" => "variant.product.group_buy"}
|
||||
%span.bulk-input-container
|
||||
%span.bulk-input
|
||||
%input.bulk.first{type: :number,
|
||||
value: nil,
|
||||
integer: true,
|
||||
min: 0,
|
||||
"ng-model" => "variant.line_item.quantity",
|
||||
placeholder: "{{'shop_variant_quantity_min' | t}}",
|
||||
"ofn-disable-scroll" => true,
|
||||
max: "{{variant.on_demand && 9999 || variant.count_on_hand }}",
|
||||
name: "variants[{{variant.id}}]", id: "variants_{{variant.id}}"}
|
||||
%span.bulk-input
|
||||
%input.bulk.second{type: :number,
|
||||
"ng-disabled" => "!variant.line_item.quantity",
|
||||
integer: true,
|
||||
min: 0,
|
||||
"ng-model" => "variant.line_item.max_quantity",
|
||||
placeholder: "{{'shop_variant_quantity_max' | t}}",
|
||||
"ofn-disable-scroll" => true,
|
||||
max: "{{variant.on_demand && 9999 || variant.count_on_hand }}",
|
||||
name: "variant_attributes[{{variant.id}}][max_quantity]"}
|
||||
%ng-include{src: "'partials/shop_variant_no_group_buy.html'"}
|
||||
%ng-include{src: "'partials/shop_variant_with_group_buy.html'"}
|
||||
|
||||
.small-3.medium-1.large-1.columns.variant-unit
|
||||
.table-cell
|
||||
.table-cell
|
||||
%em {{ variant.unit_to_display }}
|
||||
|
||||
.small-4.medium-2.large-2.columns.variant-price
|
||||
.table-cell.price
|
||||
%i.ofn-i_009-close
|
||||
%i.ofn-i_009-close
|
||||
{{ variant.price_with_fees | localizeCurrency }}
|
||||
|
||||
-# Now in a template in app/assets/javascripts/templates !
|
||||
%price-breakdown{"price-breakdown" => "_", variant: "variant",
|
||||
%price-breakdown{"price-breakdown" => "_", variant: "variant",
|
||||
"price-breakdown-append-to-body" => "true",
|
||||
"price-breakdown-placement" => "left",
|
||||
"price-breakdown-animation" => true}
|
||||
@@ -63,4 +28,4 @@
|
||||
.small-12.medium-2.large-2.columns.total-price.text-right
|
||||
.table-cell
|
||||
%strong{"ng-class" => "{filled: variant.totalPrice()}"}
|
||||
{{ variant.totalPrice() | localizeCurrency }}
|
||||
{{ variant.totalPrice() | localizeCurrency }}
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
%tab#sign-up-content{"ng-controller" => "SignupCtrl",
|
||||
heading: "{{'label_signup' | t}}",
|
||||
active: "active(path)",
|
||||
select: "select(path)"}
|
||||
%form{"ng-submit" => "submit()"}
|
||||
%tab#sign-up-content{ heading: "{{'label_signup' | t}}", active: 'tabs.signup.active', select: "select(path)"}
|
||||
%form{ ng: { controller: "SignupCtrl", submit: "submit()" } }
|
||||
.row
|
||||
.large-12.columns
|
||||
%label{for: "email"} {{'signup_email' | t}}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
*= require admin/spree_promo
|
||||
|
||||
*= require shared/jquery-ui-timepicker-addon
|
||||
*= require shared/textAngular.min
|
||||
*= require shared/textAngular
|
||||
*= require shared/ng-tags-input.min
|
||||
|
||||
*= require_self
|
||||
|
||||
@@ -1,9 +1,14 @@
|
||||
#save-bar
|
||||
position: fixed
|
||||
width: 100%
|
||||
z-index: 100
|
||||
bottom: 0px
|
||||
padding: 8px 10px
|
||||
left: 0
|
||||
padding: 8px 8px
|
||||
font-weight: bold
|
||||
background-color: #fff
|
||||
background-color: #eff5fc
|
||||
color: #5498da
|
||||
h5
|
||||
color: #5498da
|
||||
input
|
||||
margin-right: 5px
|
||||
|
||||
3
app/assets/stylesheets/admin/customers.css.scss
Normal file
3
app/assets/stylesheets/admin/customers.css.scss
Normal file
@@ -0,0 +1,3 @@
|
||||
.tag-with-rules {
|
||||
color: black;
|
||||
}
|
||||
@@ -28,6 +28,9 @@ text-angular .ta-editor {
|
||||
left: 275px;
|
||||
}
|
||||
|
||||
span.error, div.error {
|
||||
color: #DA5354;
|
||||
}
|
||||
|
||||
/* Fix conflict between Spree and elRTE's styles */
|
||||
.el-rte .toolbar {
|
||||
@@ -37,6 +40,12 @@ text-angular .ta-editor {
|
||||
|
||||
input.red {
|
||||
background-color: #DA5354;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
input.orange {
|
||||
background-color: #FF9848;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
input.search {
|
||||
|
||||
@@ -13,10 +13,6 @@ input.show-dirty {
|
||||
}
|
||||
}
|
||||
|
||||
span.error {
|
||||
color: #DA5354;
|
||||
}
|
||||
|
||||
input, div {
|
||||
&.update-error {
|
||||
border: solid 1px #DA5354;
|
||||
|
||||
@@ -11,20 +11,20 @@
|
||||
padding-bottom: 0em
|
||||
display: table
|
||||
line-height: 1.1
|
||||
// outline: 1px solid red
|
||||
// outline: 1px solid red
|
||||
|
||||
@media all and (max-width: 768px)
|
||||
font-size: 0.875rem
|
||||
@media all and (max-width: 768px)
|
||||
font-size: 0.875rem
|
||||
|
||||
@media all and (max-width: 640px)
|
||||
font-size: 0.75rem
|
||||
|
||||
@media all and (max-width: 640px)
|
||||
font-size: 0.75rem
|
||||
|
||||
.table-cell
|
||||
display: table-cell
|
||||
vertical-align: middle
|
||||
height: 37px
|
||||
|
||||
// ROW VARIANTS
|
||||
// ROW VARIANTS
|
||||
.row.variants
|
||||
margin-left: 0
|
||||
margin-right: 0
|
||||
@@ -35,7 +35,10 @@
|
||||
background-color: #f9f9f9
|
||||
&:hover, &:focus, &:active
|
||||
background-color: $clr-brick-ultra-light
|
||||
|
||||
|
||||
&.out-of-stock
|
||||
opacity: 0.2
|
||||
|
||||
// Variant name
|
||||
.variant-name
|
||||
padding-left: 7.9375rem
|
||||
@@ -52,7 +55,7 @@
|
||||
height: 27px
|
||||
|
||||
// Variant unit
|
||||
.variant-unit
|
||||
.variant-unit
|
||||
padding-left: 0rem
|
||||
padding-right: 0rem
|
||||
color: #888
|
||||
@@ -88,18 +91,18 @@
|
||||
margin-left: 0
|
||||
margin-right: 0
|
||||
background: #fff
|
||||
|
||||
|
||||
.columns
|
||||
padding-top: 1em
|
||||
padding-bottom: 1em
|
||||
line-height: 1
|
||||
|
||||
|
||||
@media all and (max-width: 768px)
|
||||
padding-top: 0.65rem
|
||||
padding-bottom: 0.65rem
|
||||
|
||||
.summary-header
|
||||
padding-left: 7.9375rem
|
||||
padding-left: 7.9375rem
|
||||
@media all and (max-width: 768px)
|
||||
padding-left: 4.9375rem
|
||||
@media all and (max-width: 640px)
|
||||
@@ -118,4 +121,3 @@
|
||||
color: $clr-brick
|
||||
i
|
||||
font-size: 0.8em
|
||||
|
||||
|
||||
@@ -32,6 +32,13 @@
|
||||
.debit
|
||||
color: $clr-brick
|
||||
|
||||
.invalid
|
||||
color: $ofn-grey
|
||||
.credit
|
||||
color: $ofn-grey
|
||||
.debit
|
||||
color: $ofn-grey
|
||||
|
||||
.distributor-balance.paid
|
||||
visibility: hidden
|
||||
|
||||
|
||||
@@ -22,7 +22,29 @@
|
||||
background: rgba(255,255,255,0.85)
|
||||
width: 50%
|
||||
margin-top: 1.2rem
|
||||
margin-left: 1rem
|
||||
@media all and (max-width: 768px)
|
||||
width: 80%
|
||||
&:active, &:focus, &.active
|
||||
background: rgba(255,255,255, 1)
|
||||
|
||||
.map-footer
|
||||
position: fixed
|
||||
z-index: 2
|
||||
width: 100%
|
||||
height: 23px
|
||||
left: 80px
|
||||
right: 0
|
||||
bottom: 6px
|
||||
margin: 0
|
||||
padding: 6px
|
||||
font-size: 14px
|
||||
font-weight: bold
|
||||
text-shadow: 2px 2px #aaa
|
||||
color: #fff
|
||||
|
||||
a, a:hover, a:active, a:focus
|
||||
color: #fff
|
||||
|
||||
@media all and (max-width: 1025px)
|
||||
left: 0px
|
||||
@@ -84,16 +84,25 @@
|
||||
padding-right: 0rem
|
||||
font-size: 0.8rem
|
||||
|
||||
.shopfront_message, .shopfront_closed_message, .shopfront_hidden_message
|
||||
.alert-box.shopfront-message
|
||||
border: 2px solid $clr-turquoise
|
||||
border-radius: 5px
|
||||
background-color: $clr-turquoise-light
|
||||
color: $clr-turquoise
|
||||
a
|
||||
color: #0096ad
|
||||
&:hover, &:focus, &:active
|
||||
text-decoration: none
|
||||
color: #4aadbd
|
||||
|
||||
|
||||
.shopfront_closed_message, .shopfront_hidden_message
|
||||
padding: 15px
|
||||
border-radius: 5px
|
||||
|
||||
.shopfront_message, .shopfront_closed_message
|
||||
.shopfront_closed_message
|
||||
border: 2px solid #eb4c46
|
||||
|
||||
.shopfront_message
|
||||
margin-top: 2em
|
||||
|
||||
.shopfront_closed_message
|
||||
margin: 2em 0em
|
||||
|
||||
|
||||
@@ -74,6 +74,9 @@ table.order-summary
|
||||
padding-left: 5px
|
||||
padding-right: 5px
|
||||
|
||||
.text-right
|
||||
text-align: right
|
||||
|
||||
.social .soc-btn
|
||||
padding: 3px 7px
|
||||
font-size: 12px
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user