mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-01-24 20:36:49 +00:00
Merge remote-tracking branch 'origin/master' into uk/spree-google-analytics
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()
|
||||
|
||||
|
||||
@@ -9,6 +9,10 @@ angular.module("admin.businessModelConfiguration").controller "BusinessModelConf
|
||||
return $scope.bill() if !$scope.cap? || Number($scope.cap) == 0
|
||||
Math.min($scope.bill(), Number($scope.cap))
|
||||
|
||||
$scope.finalBill = ->
|
||||
return 0 if Number($scope.turnover) < Number($scope.minBillableTurnover)
|
||||
$scope.cappedBill()
|
||||
|
||||
$scope.capReached = ->
|
||||
return "No" if !$scope.cap? || Number($scope.cap) == 0
|
||||
if $scope.bill() >= Number($scope.cap) then "Yes" else "No"
|
||||
@@ -18,4 +22,4 @@ angular.module("admin.businessModelConfiguration").controller "BusinessModelConf
|
||||
($scope.cappedBill() * Number($scope.taxRate))
|
||||
|
||||
$scope.total = ->
|
||||
$scope.cappedBill() + $scope.includedTax()
|
||||
$scope.finalBill() + $scope.includedTax()
|
||||
|
||||
@@ -1,43 +1,24 @@
|
||||
angular.module("admin.customers").controller "customersCtrl", ($scope, CustomerResource, TagsResource, $q, 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 "shop.id", ->
|
||||
if $scope.shop.id?
|
||||
$scope.customers = index {enterprise_id: $scope.shop.id}
|
||||
$scope.$watch "CurrentShop.shop", ->
|
||||
if $scope.CurrentShop.shop.id?
|
||||
Customers.index({enterprise_id: $scope.CurrentShop.shop.id}).then (data) ->
|
||||
$scope.customers = data
|
||||
|
||||
$scope.findTags = (query) ->
|
||||
defer = $q.defer()
|
||||
params =
|
||||
enterprise_id: $scope.shop.id
|
||||
TagsResource.index params, (data) =>
|
||||
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
|
||||
|
||||
$scope.add = (email) ->
|
||||
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
|
||||
|
||||
@@ -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,9 +0,0 @@
|
||||
angular.module("admin.customers").factory 'TagsResource', ($resource) ->
|
||||
$resource('/admin/tags.json', {}, {
|
||||
'index':
|
||||
method: 'GET'
|
||||
isArray: true
|
||||
cache: true
|
||||
params:
|
||||
enterprise_id: '@enterprise_id'
|
||||
})
|
||||
@@ -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,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', 'templates'])
|
||||
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
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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"]
|
||||
|
||||
@@ -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,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' } }
|
||||
@@ -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}}"}
|
||||
|
||||
@@ -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"}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.small-5.medium-3.large-3.columns.text-right{"bo-if" => "!variant.product.group_buy"}
|
||||
.small-5.medium-3.large-3.columns.text-right{"ng-if" => "::!variant.product.group_buy"}
|
||||
|
||||
%input{type: :number,
|
||||
integer: true,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.small-5.medium-3.large-3.columns.text-right{"bo-if" => "variant.product.group_buy"}
|
||||
.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,
|
||||
|
||||
@@ -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 }
|
||||
|
||||
@@ -2,16 +2,14 @@
|
||||
.small-12.medium-4.large-4.columns.variant-name
|
||||
.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}}
|
||||
|
||||
|
||||
%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
|
||||
%em {{ variant.unit_to_display }}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1 +1 @@
|
||||
tags-input{display:block}tags-input *,tags-input :after,tags-input :before{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}tags-input .host{position:relative;margin-top:5px;margin-bottom:5px;height:100%}tags-input .host:active{outline:0}tags-input .tags{-moz-appearance:textfield;-webkit-appearance:textfield;padding:1px;overflow:hidden;word-wrap:break-word;cursor:text;background-color:#fff;border:1px solid #a9a9a9;box-shadow:1px 1px 1px 0 #d3d3d3 inset;height:100%}tags-input .tags.focused{outline:0;-webkit-box-shadow:0 0 3px 1px rgba(5,139,242,.6);-moz-box-shadow:0 0 3px 1px rgba(5,139,242,.6);box-shadow:0 0 3px 1px rgba(5,139,242,.6)}tags-input .tags .tag-list{margin:0;padding:0;list-style-type:none}tags-input .tags .tag-item{margin:2px;padding:0 5px;display:inline-block;float:left;font:14px "Helvetica Neue",Helvetica,Arial,sans-serif;height:26px;line-height:25px;border:1px solid #acacac;border-radius:3px;background:-webkit-linear-gradient(top,#f0f9ff 0,#cbebff 47%,#a1dbff 100%);background:linear-gradient(to bottom,#f0f9ff 0,#cbebff 47%,#a1dbff 100%)}tags-input .tags .tag-item.selected{background:-webkit-linear-gradient(top,#febbbb 0,#fe9090 45%,#ff5c5c 100%);background:linear-gradient(to bottom,#febbbb 0,#fe9090 45%,#ff5c5c 100%)}tags-input .tags .tag-item .remove-button{margin:0 0 0 5px;padding:0;border:none;background:0 0;cursor:pointer;vertical-align:middle;font:700 16px Arial,sans-serif;color:#585858}tags-input .tags .tag-item .remove-button:active{color:red}tags-input .tags .input{border:0;outline:0;margin:2px;padding:0;padding-left:5px;float:left;height:26px;font:14px "Helvetica Neue",Helvetica,Arial,sans-serif}tags-input .tags .input.invalid-tag{color:red}tags-input .tags .input::-ms-clear{display:none}tags-input.ng-invalid .tags{-webkit-box-shadow:0 0 3px 1px rgba(255,0,0,.6);-moz-box-shadow:0 0 3px 1px rgba(255,0,0,.6);box-shadow:0 0 3px 1px rgba(255,0,0,.6)}tags-input[disabled] .host:focus{outline:0}tags-input[disabled] .tags{background-color:#eee;cursor:default}tags-input[disabled] .tags .tag-item{opacity:.65;background:-webkit-linear-gradient(top,#f0f9ff 0,rgba(203,235,255,.75)47%,rgba(161,219,255,.62)100%);background:linear-gradient(to bottom,#f0f9ff 0,rgba(203,235,255,.75)47%,rgba(161,219,255,.62)100%)}tags-input[disabled] .tags .tag-item .remove-button{cursor:default}tags-input[disabled] .tags .tag-item .remove-button:active{color:#585858}tags-input[disabled] .tags .input{background-color:#eee;cursor:default}tags-input .autocomplete{margin-top:5px;position:absolute;padding:5px 0;z-index:999;width:100%;background-color:#fff;border:1px solid rgba(0,0,0,.2);-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);-moz-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2)}tags-input .autocomplete .suggestion-list{margin:0;padding:0;list-style-type:none;max-height:280px;overflow-y:auto;position:relative}tags-input .autocomplete .suggestion-item{padding:5px 10px;cursor:pointer;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font:16px "Helvetica Neue",Helvetica,Arial,sans-serif;color:#000;background-color:#fff}tags-input .autocomplete .suggestion-item.selected,tags-input .autocomplete .suggestion-item.selected em{color:#fff;background-color:#0097cf}tags-input .autocomplete .suggestion-item em{font:normal bold 16px "Helvetica Neue",Helvetica,Arial,sans-serif;color:#000;background-color:#fff}
|
||||
tags-input{display:block}tags-input *,tags-input :after,tags-input :before{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}tags-input .host{position:relative;margin-top:5px;margin-bottom:5px;height:100%}tags-input .host:active{outline:0}tags-input .tags{-moz-appearance:textfield;-webkit-appearance:textfield;padding:1px;overflow:hidden;word-wrap:break-word;cursor:text;background-color:#fff;border:1px solid #a9a9a9;box-shadow:1px 1px 1px 0 #d3d3d3 inset;height:100%}tags-input .tags.focused{outline:0;-webkit-box-shadow:0 0 3px 1px rgba(5,139,242,.6);-moz-box-shadow:0 0 3px 1px rgba(5,139,242,.6);box-shadow:0 0 3px 1px rgba(5,139,242,.6)}tags-input .tags .tag-list{margin:0;padding:0;list-style-type:none}tags-input .tags .tag-item{margin:2px;padding:0 5px;display:inline-block;float:left;font:14px "Helvetica Neue",Helvetica,Arial,sans-serif;height:26px;line-height:25px;border:1px solid #acacac;border-radius:3px;background:-webkit-linear-gradient(top,#f0f9ff 0,#cbebff 47%,#a1dbff 100%);background:linear-gradient(to bottom,#f0f9ff 0,#cbebff 47%,#a1dbff 100%)}tags-input .tags .tag-item.selected{background:-webkit-linear-gradient(top,#febbbb 0,#fe9090 45%,#ff5c5c 100%);background:linear-gradient(to bottom,#febbbb 0,#fe9090 45%,#ff5c5c 100%)}tags-input .tags .tag-item .remove-button{margin:0 0 0 5px;padding:0;border:none;background:0 0;cursor:pointer;vertical-align:middle;font:700 16px Arial,sans-serif;color:#585858}tags-input .tags .input.invalid-tag,tags-input .tags .tag-item .remove-button:active{color:red}tags-input .tags .input{border:0;outline:0;margin:2px;padding:0 0 0 5px;float:left;height:26px;font:14px "Helvetica Neue",Helvetica,Arial,sans-serif}tags-input .tags .input::-ms-clear{display:none}tags-input.ng-invalid .tags{-webkit-box-shadow:0 0 3px 1px rgba(255,0,0,.6);-moz-box-shadow:0 0 3px 1px rgba(255,0,0,.6);box-shadow:0 0 3px 1px rgba(255,0,0,.6)}tags-input[disabled] .host:focus{outline:0}tags-input[disabled] .tags{background-color:#eee;cursor:default}tags-input[disabled] .tags .tag-item{opacity:.65;background:-webkit-linear-gradient(top,#f0f9ff 0,rgba(203,235,255,.75)47%,rgba(161,219,255,.62)100%);background:linear-gradient(to bottom,#f0f9ff 0,rgba(203,235,255,.75)47%,rgba(161,219,255,.62)100%)}tags-input[disabled] .tags .tag-item .remove-button{cursor:default}tags-input[disabled] .tags .tag-item .remove-button:active{color:#585858}tags-input[disabled] .tags .input{background-color:#eee;cursor:default}tags-input .autocomplete{margin-top:5px;position:absolute;padding:5px 0;z-index:999;width:100%;background-color:#fff;border:1px solid rgba(0,0,0,.2);-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);-moz-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2)}tags-input .autocomplete .suggestion-list{margin:0;padding:0;list-style-type:none;max-height:280px;overflow-y:auto;position:relative}tags-input .autocomplete .suggestion-item{padding:5px 10px;cursor:pointer;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font:16px "Helvetica Neue",Helvetica,Arial,sans-serif;color:#000;background-color:#fff}tags-input .autocomplete .suggestion-item.selected,tags-input .autocomplete .suggestion-item.selected em{color:#fff;background-color:#0097cf}tags-input .autocomplete .suggestion-item em{font:normal bold 16px "Helvetica Neue",Helvetica,Arial,sans-serif;color:#000;background-color:#fff}
|
||||
|
||||
193
app/assets/stylesheets/shared/textAngular.css
Normal file
193
app/assets/stylesheets/shared/textAngular.css
Normal file
@@ -0,0 +1,193 @@
|
||||
.ta-hidden-input {
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
border: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
position: absolute;
|
||||
top: -10000px;
|
||||
left: -10000px;
|
||||
opacity: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* add generic styling for the editor */
|
||||
.ta-root.focussed > .ta-scroll-window.form-control {
|
||||
border-color: #66afe9;
|
||||
outline: 0;
|
||||
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6);
|
||||
-moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6);
|
||||
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6);
|
||||
}
|
||||
|
||||
.ta-editor.ta-html, .ta-scroll-window.form-control {
|
||||
min-height: 300px;
|
||||
height: auto;
|
||||
overflow: auto;
|
||||
font-family: inherit;
|
||||
font-size: 100%;
|
||||
}
|
||||
|
||||
.ta-scroll-window.form-control {
|
||||
position: relative;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.ta-scroll-window > .ta-bind {
|
||||
height: auto;
|
||||
min-height: 300px;
|
||||
padding: 6px 12px;
|
||||
}
|
||||
|
||||
.ta-editor:focus {
|
||||
user-select: text;
|
||||
}
|
||||
|
||||
/* add the styling for the awesomness of the resizer */
|
||||
.ta-resizer-handle-overlay {
|
||||
z-index: 100;
|
||||
position: absolute;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.ta-resizer-handle-overlay > .ta-resizer-handle-info {
|
||||
position: absolute;
|
||||
bottom: 16px;
|
||||
right: 16px;
|
||||
border: 1px solid black;
|
||||
background-color: #FFF;
|
||||
padding: 0 4px;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.ta-resizer-handle-overlay > .ta-resizer-handle-background {
|
||||
position: absolute;
|
||||
bottom: 5px;
|
||||
right: 5px;
|
||||
left: 5px;
|
||||
top: 5px;
|
||||
border: 1px solid black;
|
||||
background-color: rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.ta-resizer-handle-overlay > .ta-resizer-handle-corner {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.ta-resizer-handle-overlay > .ta-resizer-handle-corner-tl{
|
||||
top: 0;
|
||||
left: 0;
|
||||
border-left: 1px solid black;
|
||||
border-top: 1px solid black;
|
||||
}
|
||||
|
||||
.ta-resizer-handle-overlay > .ta-resizer-handle-corner-tr{
|
||||
top: 0;
|
||||
right: 0;
|
||||
border-right: 1px solid black;
|
||||
border-top: 1px solid black;
|
||||
}
|
||||
|
||||
.ta-resizer-handle-overlay > .ta-resizer-handle-corner-bl{
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
border-left: 1px solid black;
|
||||
border-bottom: 1px solid black;
|
||||
}
|
||||
|
||||
.ta-resizer-handle-overlay > .ta-resizer-handle-corner-br{
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
border: 1px solid black;
|
||||
cursor: se-resize;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
/* copy the popover code from bootstrap so this will work even without it */
|
||||
.popover {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 1060;
|
||||
display: none;
|
||||
max-width: 276px;
|
||||
padding: 1px;
|
||||
font-size: 14px;
|
||||
font-weight: normal;
|
||||
line-height: 1.42857143;
|
||||
text-align: left;
|
||||
white-space: normal;
|
||||
background-color: #fff;
|
||||
-webkit-background-clip: padding-box;
|
||||
background-clip: padding-box;
|
||||
border: 1px solid #ccc;
|
||||
border: 1px solid rgba(0, 0, 0, .2);
|
||||
border-radius: 6px;
|
||||
-webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, .2);
|
||||
box-shadow: 0 5px 10px rgba(0, 0, 0, .2);
|
||||
}
|
||||
.popover.top {
|
||||
margin-top: -10px;
|
||||
}
|
||||
.popover.bottom {
|
||||
margin-top: 10px;
|
||||
}
|
||||
.popover-title {
|
||||
padding: 8px 14px;
|
||||
margin: 0;
|
||||
font-size: 14px;
|
||||
background-color: #f7f7f7;
|
||||
border-bottom: 1px solid #ebebeb;
|
||||
border-radius: 5px 5px 0 0;
|
||||
}
|
||||
.popover-content {
|
||||
padding: 9px 14px;
|
||||
}
|
||||
.popover > .arrow,
|
||||
.popover > .arrow:after {
|
||||
position: absolute;
|
||||
display: block;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-color: transparent;
|
||||
border-style: solid;
|
||||
}
|
||||
.popover > .arrow {
|
||||
border-width: 11px;
|
||||
}
|
||||
.popover > .arrow:after {
|
||||
content: "";
|
||||
border-width: 10px;
|
||||
}
|
||||
.popover.top > .arrow {
|
||||
bottom: -11px;
|
||||
left: 50%;
|
||||
margin-left: -11px;
|
||||
border-top-color: #999;
|
||||
border-top-color: rgba(0, 0, 0, .25);
|
||||
border-bottom-width: 0;
|
||||
}
|
||||
.popover.top > .arrow:after {
|
||||
bottom: 1px;
|
||||
margin-left: -10px;
|
||||
content: " ";
|
||||
border-top-color: #fff;
|
||||
border-bottom-width: 0;
|
||||
}
|
||||
.popover.bottom > .arrow {
|
||||
top: -11px;
|
||||
left: 50%;
|
||||
margin-left: -11px;
|
||||
border-top-width: 0;
|
||||
border-bottom-color: #999;
|
||||
border-bottom-color: rgba(0, 0, 0, .25);
|
||||
}
|
||||
.popover.bottom > .arrow:after {
|
||||
top: 1px;
|
||||
margin-left: -10px;
|
||||
content: " ";
|
||||
border-top-width: 0;
|
||||
border-bottom-color: #fff;
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
.ta-scroll-window.form-control{height:auto;min-height:300px;overflow:auto;font-family:inherit;font-size:100%;position:relative;padding:0}.ta-root.focussed .ta-scroll-window.form-control{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.ta-editor.ta-html{min-height:300px;height:auto;overflow:auto;font-family:inherit;font-size:100%}.ta-scroll-window>.ta-bind{height:auto;min-height:300px;padding:6px 12px}.ta-root .ta-resizer-handle-overlay{z-index:100;position:absolute;display:none}.ta-root .ta-resizer-handle-overlay>.ta-resizer-handle-info{position:absolute;bottom:16px;right:16px;border:1px solid #000;background-color:#FFF;padding:0 4px;opacity:.7}.ta-root .ta-resizer-handle-overlay>.ta-resizer-handle-background{position:absolute;bottom:5px;right:5px;left:5px;top:5px;border:1px solid #000;background-color:rgba(0,0,0,.2)}.ta-root .ta-resizer-handle-overlay>.ta-resizer-handle-corner{width:10px;height:10px;position:absolute}.ta-root .ta-resizer-handle-overlay>.ta-resizer-handle-corner-tl{top:0;left:0;border-left:1px solid #000;border-top:1px solid #000}.ta-root .ta-resizer-handle-overlay>.ta-resizer-handle-corner-tr{top:0;right:0;border-right:1px solid #000;border-top:1px solid #000}.ta-root .ta-resizer-handle-overlay>.ta-resizer-handle-corner-bl{bottom:0;left:0;border-left:1px solid #000;border-bottom:1px solid #000}.ta-root .ta-resizer-handle-overlay>.ta-resizer-handle-corner-br{bottom:0;right:0;border:1px solid #000;cursor:se-resize;background-color:#fff}
|
||||
@@ -18,10 +18,13 @@ class Admin::BusinessModelConfigurationController < Spree::Admin::BaseController
|
||||
|
||||
def load_settings
|
||||
@settings = OpenFoodNetwork::BusinessModelConfigurationValidator.new(params[:settings] || {
|
||||
shop_trial_length_days: Spree::Config[:shop_trial_length_days],
|
||||
account_invoices_monthly_fixed: Spree::Config[:account_invoices_monthly_fixed],
|
||||
account_invoices_monthly_rate: Spree::Config[:account_invoices_monthly_rate],
|
||||
account_invoices_monthly_cap: Spree::Config[:account_invoices_monthly_cap],
|
||||
account_invoices_tax_rate: Spree::Config[:account_invoices_tax_rate]
|
||||
account_invoices_tax_rate: Spree::Config[:account_invoices_tax_rate],
|
||||
minimum_billable_turnover: Spree::Config[:minimum_billable_turnover]
|
||||
|
||||
})
|
||||
end
|
||||
|
||||
|
||||
38
app/controllers/admin/column_preferences_controller.rb
Normal file
38
app/controllers/admin/column_preferences_controller.rb
Normal file
@@ -0,0 +1,38 @@
|
||||
module Admin
|
||||
class ColumnPreferencesController < ResourceController
|
||||
before_filter :load_collection, only: [:bulk_update]
|
||||
|
||||
respond_to :json
|
||||
|
||||
def bulk_update
|
||||
@cp_set.collection.each { |cp| authorize! :bulk_update, cp }
|
||||
|
||||
if @cp_set.save
|
||||
# Return saved VOs with IDs
|
||||
render json: @cp_set.collection, each_serializer: Api::Admin::ColumnPreferenceSerializer
|
||||
else
|
||||
if @cp_set.errors.present?
|
||||
render json: { errors: @cp_set.errors }, status: 400
|
||||
else
|
||||
render nothing: true, status: 500
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def load_collection
|
||||
collection_hash = Hash[params[:column_preferences].each_with_index.map { |cp, i| [i, cp] }]
|
||||
collection_hash.reject!{ |i, cp| cp[:action_name] != params[:action_name] }
|
||||
@cp_set = ColumnPreferenceSet.new @column_preferences, collection_attributes: collection_hash
|
||||
end
|
||||
|
||||
def collection
|
||||
ColumnPreference.where(user_id: spree_current_user, action_name: params[:action_name])
|
||||
end
|
||||
|
||||
def collection_actions
|
||||
[:bulk_update]
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -7,11 +7,8 @@ module Admin
|
||||
respond_to do |format|
|
||||
format.html
|
||||
format.json do
|
||||
serialised = ActiveModel::ArraySerializer.new(
|
||||
@collection,
|
||||
each_serializer: Api::Admin::CustomerSerializer,
|
||||
spree_current_user: spree_current_user)
|
||||
render json: serialised.to_json
|
||||
tag_rule_mapping = TagRule.mapping_for(Enterprise.where(id: params[:enterprise_id]))
|
||||
render_as_json @collection, tag_rule_mapping: tag_rule_mapping
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -19,8 +16,12 @@ module Admin
|
||||
def create
|
||||
@customer = Customer.new(params[:customer])
|
||||
if user_can_create_customer?
|
||||
@customer.save
|
||||
render json: Api::Admin::CustomerSerializer.new(@customer).to_json
|
||||
if @customer.save
|
||||
tag_rule_mapping = TagRule.mapping_for(Enterprise.where(id: @customer.enterprise))
|
||||
render_as_json @customer, tag_rule_mapping: tag_rule_mapping
|
||||
else
|
||||
render json: { errors: @customer.errors.full_messages }, status: 400
|
||||
end
|
||||
else
|
||||
redirect_to '/unauthorized'
|
||||
end
|
||||
|
||||
@@ -6,5 +6,38 @@ module Admin
|
||||
respond_override destroy: { json: {
|
||||
success: lambda { render nothing: true, :status => 204 }
|
||||
} }
|
||||
|
||||
def map_by_tag
|
||||
respond_to do |format|
|
||||
format.json do
|
||||
serialiser = ActiveModel::ArraySerializer.new(collection)
|
||||
render json: serialiser.to_json
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
private
|
||||
|
||||
def collection_actions
|
||||
[:index, :map_by_tag]
|
||||
end
|
||||
|
||||
def collection
|
||||
case action
|
||||
when :map_by_tag
|
||||
TagRule.mapping_for(enterprises).values
|
||||
else
|
||||
TagRule.for(enterprises.pluck(&:id))
|
||||
end
|
||||
end
|
||||
|
||||
def enterprises
|
||||
if params[:enterprise_id]
|
||||
Enterprise.managed_by(spree_current_user).where(id: params[:enterprise_id])
|
||||
else
|
||||
Enterprise.managed_by(spree_current_user)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
module Admin
|
||||
class TagsController < Spree::Admin::BaseController
|
||||
respond_to :json
|
||||
|
||||
def index
|
||||
respond_to do |format|
|
||||
format.json do
|
||||
serialiser = ActiveModel::ArraySerializer.new(tags_of_enterprise)
|
||||
render json: serialiser.to_json
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def enterprise
|
||||
Enterprise.managed_by(spree_current_user).find_by_id(params[:enterprise_id])
|
||||
end
|
||||
|
||||
def tags_of_enterprise
|
||||
return [] unless enterprise
|
||||
tag_rule_map = enterprise.rules_per_tag
|
||||
tag_rule_map.keys.map do |tag|
|
||||
{ text: tag, rules: tag_rule_map[tag] }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -47,13 +47,19 @@ module Admin
|
||||
admin_inject_json_ams_array opts[:module], "inventoryItems", @inventory_items, Api::Admin::InventoryItemSerializer
|
||||
end
|
||||
|
||||
def admin_inject_column_preferences(opts={})
|
||||
opts.reverse_merge!(module: 'ofn.admin', action: "#{controller_name}_#{action_name}")
|
||||
column_preferences = ColumnPreference.for(spree_current_user, opts[:action])
|
||||
admin_inject_json_ams_array opts[:module], "columns", column_preferences, Api::Admin::ColumnPreferenceSerializer
|
||||
end
|
||||
|
||||
def admin_inject_enterprise_permissions
|
||||
permissions =
|
||||
{can_manage_shipping_methods: can?(:manage_shipping_methods, @enterprise),
|
||||
can_manage_payment_methods: can?(:manage_payment_methods, @enterprise),
|
||||
can_manage_enterprise_fees: can?(:manage_enterprise_fees, @enterprise)}
|
||||
|
||||
render partial: "admin/json/injection_ams", locals: {ngModule: "admin.enterprises", name: "enterprisePermissions", json: permissions.to_json}
|
||||
admin_inject_json "admin.enterprises", "enterprisePermissions", permissions
|
||||
end
|
||||
|
||||
def admin_inject_hub_permissions
|
||||
@@ -96,6 +102,11 @@ module Admin
|
||||
render partial: "admin/json/injection_ams", locals: {ngModule: 'admin.indexUtils', name: 'SpreeApiKey', json: "'#{@spree_api_key.to_s}'"}
|
||||
end
|
||||
|
||||
def admin_inject_json(ngModule, name, data)
|
||||
json = data.to_json
|
||||
render partial: "admin/json/injection_ams", locals: {ngModule: ngModule, name: name, json: json}
|
||||
end
|
||||
|
||||
def admin_inject_json_ams(ngModule, name, data, serializer, opts = {})
|
||||
json = serializer.new(data, scope: spree_current_user).to_json
|
||||
render partial: "admin/json/injection_ams", locals: {ngModule: ngModule, name: name, json: json}
|
||||
|
||||
@@ -52,17 +52,17 @@ module EnterprisesHelper
|
||||
|
||||
def shop_trial_in_progress?(enterprise)
|
||||
!!enterprise.shop_trial_start_date &&
|
||||
(enterprise.shop_trial_start_date + Enterprise::SHOP_TRIAL_LENGTH.days > Time.zone.now) &&
|
||||
(enterprise.shop_trial_start_date + Spree::Config[:shop_trial_length_days].days > Time.zone.now) &&
|
||||
%w(own any).include?(enterprise.sells)
|
||||
end
|
||||
|
||||
def shop_trial_expired?(enterprise)
|
||||
!!enterprise.shop_trial_start_date &&
|
||||
(enterprise.shop_trial_start_date + Enterprise::SHOP_TRIAL_LENGTH.days <= Time.zone.now) &&
|
||||
(enterprise.shop_trial_start_date + Spree::Config[:shop_trial_length_days].days <= Time.zone.now) &&
|
||||
%w(own any).include?(enterprise.sells)
|
||||
end
|
||||
|
||||
def remaining_trial_days(enterprise)
|
||||
distance_of_time_in_words(Time.zone.now, enterprise.shop_trial_start_date + Enterprise::SHOP_TRIAL_LENGTH.days)
|
||||
distance_of_time_in_words(Time.zone.now, enterprise.shop_trial_start_date + Spree::Config[:shop_trial_length_days].days)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -4,8 +4,11 @@ class ProducerMailer < Spree::BaseMailer
|
||||
@producer = producer
|
||||
@coordinator = order_cycle.coordinator
|
||||
@order_cycle = order_cycle
|
||||
@line_items = aggregated_line_items_from(@order_cycle, @producer)
|
||||
line_items = line_items_from(@order_cycle, @producer)
|
||||
@grouped_line_items = line_items.group_by(&:product_and_full_name)
|
||||
@receival_instructions = @order_cycle.receival_instructions_for @producer
|
||||
@total = total_from_line_items(line_items)
|
||||
@tax_total = tax_total_from_line_items(line_items)
|
||||
|
||||
subject = "[#{Spree::Config.site_name}] Order cycle report for #{producer.name}"
|
||||
|
||||
@@ -25,10 +28,6 @@ class ProducerMailer < Spree::BaseMailer
|
||||
line_items_from(order_cycle, producer).any?
|
||||
end
|
||||
|
||||
def aggregated_line_items_from(order_cycle, producer)
|
||||
aggregate_line_items line_items_from(order_cycle, producer)
|
||||
end
|
||||
|
||||
def line_items_from(order_cycle, producer)
|
||||
Spree::LineItem.
|
||||
joins(:order => :order_cycle, :variant => :product).
|
||||
@@ -37,16 +36,11 @@ class ProducerMailer < Spree::BaseMailer
|
||||
merge(Spree::Order.complete)
|
||||
end
|
||||
|
||||
def aggregate_line_items(line_items)
|
||||
# Arrange the items in a hash to group quantities
|
||||
line_items.inject({}) do |lis, li|
|
||||
if lis.key? li.variant
|
||||
lis[li.variant].quantity += li.quantity
|
||||
else
|
||||
lis[li.variant] = li
|
||||
end
|
||||
def total_from_line_items(line_items)
|
||||
Spree::Money.new line_items.sum(&:total)
|
||||
end
|
||||
|
||||
lis
|
||||
end
|
||||
def tax_total_from_line_items(line_items)
|
||||
Spree::Money.new line_items.sum(&:included_tax)
|
||||
end
|
||||
end
|
||||
|
||||
46
app/models/column_preference.rb
Normal file
46
app/models/column_preference.rb
Normal file
@@ -0,0 +1,46 @@
|
||||
require 'open_food_network/column_preference_defaults'
|
||||
|
||||
class ColumnPreference < ActiveRecord::Base
|
||||
extend OpenFoodNetwork::ColumnPreferenceDefaults
|
||||
|
||||
# These are the attributes used to identify a preference
|
||||
attr_accessible :user_id, :action_name, :column_name
|
||||
|
||||
# These are attributes that need to be mass assignable
|
||||
attr_accessible :name, :visible
|
||||
|
||||
# Non-persisted attributes that only have one
|
||||
# setting (ie. the default) for a given column
|
||||
attr_accessor :name
|
||||
|
||||
belongs_to :user, class_name: "Spree::User"
|
||||
|
||||
validates :action_name, presence: true, inclusion: { in: proc { known_actions } }
|
||||
validates :column_name, presence: true, inclusion: { in: proc { |p| valid_columns_for(p.action_name) } }
|
||||
|
||||
def self.for(user, action_name)
|
||||
stored_preferences = where(user_id: user.id, action_name: action_name)
|
||||
default_preferences = send("#{action_name}_columns")
|
||||
default_preferences.each_with_object([]) do |(column_name, default_attributes), preferences|
|
||||
stored_preference = stored_preferences.find_by_column_name(column_name)
|
||||
if stored_preference
|
||||
stored_preference.assign_attributes(default_attributes.select{ |k,v| stored_preference[k].nil? })
|
||||
preferences << stored_preference
|
||||
else
|
||||
attributes = default_attributes.merge(user_id: user.id, action_name: action_name, column_name: column_name)
|
||||
preferences << ColumnPreference.new(attributes)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def self.valid_columns_for(action_name)
|
||||
send("#{action_name}_columns").keys.map(&:to_s)
|
||||
end
|
||||
|
||||
def self.known_actions
|
||||
OpenFoodNetwork::ColumnPreferenceDefaults.private_instance_methods
|
||||
.select{|m| m.to_s.end_with?("_columns")}.map{ |m| m.to_s.sub /_columns$/, ''}
|
||||
end
|
||||
end
|
||||
5
app/models/column_preference_set.rb
Normal file
5
app/models/column_preference_set.rb
Normal file
@@ -0,0 +1,5 @@
|
||||
class ColumnPreferenceSet < ModelSet
|
||||
def initialize(collection, attributes={})
|
||||
super(ColumnPreference, collection, attributes, nil, nil )
|
||||
end
|
||||
end
|
||||
@@ -1,6 +1,5 @@
|
||||
class Enterprise < ActiveRecord::Base
|
||||
SELLS = %w(unspecified none own any)
|
||||
SHOP_TRIAL_LENGTH = 30
|
||||
ENTERPRISE_SEARCH_RADIUS = 100
|
||||
|
||||
preference :shopfront_message, :text, default: ""
|
||||
@@ -338,7 +337,7 @@ class Enterprise < ActiveRecord::Base
|
||||
end
|
||||
|
||||
def shop_trial_expiry
|
||||
shop_trial_start_date.andand + Enterprise::SHOP_TRIAL_LENGTH.days
|
||||
shop_trial_start_date.andand + Spree::Config[:shop_trial_length_days].days
|
||||
end
|
||||
|
||||
def can_invoice?
|
||||
@@ -352,20 +351,6 @@ class Enterprise < ActiveRecord::Base
|
||||
end
|
||||
end
|
||||
|
||||
def rules_per_tag
|
||||
tag_rule_map = {}
|
||||
tag_rules.each do |rule|
|
||||
rule.preferred_customer_tags.split(",").each do |tag|
|
||||
if tag_rule_map[tag]
|
||||
tag_rule_map[tag] += 1
|
||||
else
|
||||
tag_rule_map[tag] = 1
|
||||
end
|
||||
end
|
||||
end
|
||||
tag_rule_map
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def devise_mailer
|
||||
|
||||
@@ -72,7 +72,7 @@ class AbilityDecorator
|
||||
|
||||
can [:admin, :index, :read, :create, :edit, :update_positions, :destroy], ProducerProperty
|
||||
|
||||
can [:admin, :destroy], TagRule do |tag_rule|
|
||||
can [:admin, :map_by_tag, :destroy], TagRule do |tag_rule|
|
||||
user.enterprises.include? tag_rule.enterprise
|
||||
end
|
||||
|
||||
@@ -101,6 +101,10 @@ class AbilityDecorator
|
||||
can [:print], Spree::Order do |order|
|
||||
order.user == user
|
||||
end
|
||||
|
||||
can [:admin, :bulk_update], ColumnPreference do |column_preference|
|
||||
column_preference.user == user
|
||||
end
|
||||
end
|
||||
|
||||
def add_product_management_abilities(user)
|
||||
@@ -218,7 +222,6 @@ class AbilityDecorator
|
||||
|
||||
can [:create], Customer
|
||||
can [:admin, :index, :update, :destroy], Customer, enterprise_id: Enterprise.managed_by(user).pluck(:id)
|
||||
can [:admin, :index], :tag
|
||||
end
|
||||
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user