mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-03-16 04:24:23 +00:00
Merge branch 'master' into ent_types_frontend
This commit is contained in:
@@ -15,6 +15,8 @@
|
||||
#= require ../shared/bindonce.min.js
|
||||
#= require ../shared/ng-infinite-scroll.min.js
|
||||
#= require ../shared/angular-local-storage.js
|
||||
#= require angularjs-file-upload
|
||||
|
||||
|
||||
#= require angular-rails-templates
|
||||
#= require_tree ../templates
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
angular.module('Darkswarm').controller "EnterpriseImageCtrl", ($scope, EnterpriseImageService) ->
|
||||
$scope.imageStep = 'logo'
|
||||
|
||||
$scope.imageSteps = ['logo', 'promo']
|
||||
|
||||
$scope.imageUploader = EnterpriseImageService.imageUploader
|
||||
|
||||
$scope.imageSelect = (image_step) ->
|
||||
EnterpriseImageService.imageSrc = null
|
||||
$scope.imageStep = image_step
|
||||
|
||||
$scope.imageSrc = ->
|
||||
EnterpriseImageService.imageSrc
|
||||
@@ -12,4 +12,4 @@ Darkswarm.controller "RegistrationFormCtrl", ($scope, RegistrationService, Enter
|
||||
EnterpriseRegistrationService.update(nextStep) if $scope.valid(form)
|
||||
|
||||
$scope.selectIfValid = (nextStep, form) ->
|
||||
RegistrationService.select(nextStep) if $scope.valid(form)
|
||||
RegistrationService.select(nextStep) if $scope.valid(form)
|
||||
|
||||
@@ -1,18 +1,19 @@
|
||||
window.Darkswarm = angular.module("Darkswarm", ["ngResource",
|
||||
'mm.foundation',
|
||||
'angularLocalStorage',
|
||||
'pasvaz.bindonce',
|
||||
'infinite-scroll',
|
||||
'angular-flash.service',
|
||||
window.Darkswarm = angular.module("Darkswarm", ["ngResource",
|
||||
'mm.foundation',
|
||||
'angularLocalStorage',
|
||||
'pasvaz.bindonce',
|
||||
'infinite-scroll',
|
||||
'angular-flash.service',
|
||||
'templates',
|
||||
'ngSanitize',
|
||||
'ngAnimate',
|
||||
'google-maps',
|
||||
'duScroll',
|
||||
'angularFileUpload',
|
||||
]).config ($httpProvider, $tooltipProvider, $locationProvider, $anchorScrollProvider) ->
|
||||
$httpProvider.defaults.headers.post['X-CSRF-Token'] = $('meta[name="csrf-token"]').attr('content')
|
||||
$httpProvider.defaults.headers.put['X-CSRF-Token'] = $('meta[name="csrf-token"]').attr('content')
|
||||
$httpProvider.defaults.headers['common']['X-Requested-With'] = 'XMLHttpRequest'
|
||||
$httpProvider.defaults.headers.post['X-CSRF-Token'] = $('meta[name="csrf-token"]').attr('content')
|
||||
$httpProvider.defaults.headers.put['X-CSRF-Token'] = $('meta[name="csrf-token"]').attr('content')
|
||||
$httpProvider.defaults.headers['common']['X-Requested-With'] = 'XMLHttpRequest'
|
||||
$httpProvider.defaults.headers.common.Accept = "application/json, text/javascript, */*"
|
||||
|
||||
# This allows us to trigger these two events on tooltips
|
||||
@@ -20,4 +21,3 @@ window.Darkswarm = angular.module("Darkswarm", ["ngResource",
|
||||
|
||||
# We manually handle our scrolling
|
||||
$anchorScrollProvider.disableAutoScrolling()
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
Darkswarm.factory "EnterpriseImageService", (FileUploader, spreeApiKey) ->
|
||||
new class EnterpriseImageService
|
||||
imageSrc: null
|
||||
|
||||
imageUploader: new FileUploader
|
||||
headers:
|
||||
'X-Spree-Token': spreeApiKey
|
||||
autoUpload: true
|
||||
|
||||
configure: (enterprise) =>
|
||||
@imageUploader.url = "/api/enterprises/#{enterprise.id}/update_image"
|
||||
@imageUploader.onSuccessItem = (image, response) => @imageSrc = response
|
||||
@@ -1,4 +1,4 @@
|
||||
Darkswarm.factory "EnterpriseRegistrationService", ($http, RegistrationService, CurrentUser, spreeApiKey, Loading, availableCountries, enterpriseAttributes) ->
|
||||
Darkswarm.factory "EnterpriseRegistrationService", ($http, RegistrationService, EnterpriseImageService, CurrentUser, spreeApiKey, Loading, availableCountries, enterpriseAttributes) ->
|
||||
new class EnterpriseRegistrationService
|
||||
enterprise:
|
||||
user_ids: [CurrentUser.id]
|
||||
@@ -22,6 +22,7 @@ Darkswarm.factory "EnterpriseRegistrationService", ($http, RegistrationService,
|
||||
).success((data) =>
|
||||
Loading.clear()
|
||||
@enterprise.id = data
|
||||
EnterpriseImageService.configure(@enterprise)
|
||||
RegistrationService.select('about')
|
||||
).error((data) =>
|
||||
Loading.clear()
|
||||
@@ -54,4 +55,4 @@ Darkswarm.factory "EnterpriseRegistrationService", ($http, RegistrationService,
|
||||
enterprise[key] = value
|
||||
enterprise.address_attributes = @enterprise.address if @enterprise.address?
|
||||
enterprise.address_attributes.country_id = @enterprise.country.id if @enterprise.country?
|
||||
enterprise
|
||||
enterprise
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Darkswarm.factory "RegistrationService", (Navigation, $modal, Loading)->
|
||||
angular.module('Darkswarm').factory "RegistrationService", (Navigation, $modal, Loading)->
|
||||
|
||||
new class RegistrationService
|
||||
constructor: ->
|
||||
@@ -20,4 +20,4 @@ Darkswarm.factory "RegistrationService", (Navigation, $modal, Loading)->
|
||||
|
||||
close: ->
|
||||
Loading.message = "Taking you back to the home page"
|
||||
Navigation.go "/"
|
||||
Navigation.go "/"
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
{{ enterprise.name }}
|
||||
|
||||
%ng-include{ src: "'registration/steps.html'" }
|
||||
%form{ name: 'about', novalidate: true, ng: { controller: "RegistrationFormCtrl", submit: "update('social',about)" } }
|
||||
%form{ name: 'about', novalidate: true, ng: { controller: "RegistrationFormCtrl", submit: "update('images',about)" } }
|
||||
.row
|
||||
.small-12.columns
|
||||
.alert-box.alert{"data-alert" => ""}
|
||||
|
||||
@@ -1,14 +1,20 @@
|
||||
.container#registration-images
|
||||
.container#registration-images{ 'nv-file-drop' => true, uploader: "imageUploader", options:"{ alias: imageStep }", ng: { controller: "EnterpriseImageCtrl" } }
|
||||
.header
|
||||
%h2 Thanks!
|
||||
%h5 Let's upload some pretty pictures so your profile looks great! :)
|
||||
%ng-include{ src: "'registration/steps.html'" }
|
||||
.row.content
|
||||
%form{ name: 'images', novalidate: true, ng: { controller: "RegistrationFormCtrl", submit: "select('social')" } }
|
||||
.row{ ng: { repeat: 'image_step in imageSteps', show: "imageStep == image_step" } }
|
||||
%ng-include{ src: "'registration/images/'+ image_step + '.html'" }
|
||||
|
||||
.row.buttons
|
||||
.small-12.columns
|
||||
%input.button.primary.left{ type: "button", value: "Back", ng: { click: "select('about')" } }
|
||||
|
||||
%input.button.primary.right{ type: "button", value: "Continue", ng: { click: "select('social')" } }
|
||||
|
||||
|
||||
.row.buttons.pad-top{ ng: { if: "imageStep == 'logo'" } }
|
||||
.small-12.columns
|
||||
%input.button.primary{ type: "button", value: "Back", ng: { click: "select('about')" } }
|
||||
|
||||
%input.button.primary{ type: "button", value: "Continue", ng: { click: "imageSelect('promo')" } }
|
||||
|
||||
.row.buttons.pad-top{ ng: { if: "imageStep == 'promo'" } }
|
||||
.small-12.columns
|
||||
%input.button.primary{ type: "button", value: "Back", ng: { click: "imageSelect('logo')" } }
|
||||
|
||||
%input.button.primary{ type: "submit", value: "Continue" }
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
.small-12.medium-12.large-6.columns
|
||||
.row
|
||||
.small-12.columns.center
|
||||
.row
|
||||
.small-12.columns.center
|
||||
%h4
|
||||
Step 1. Select Logo Image
|
||||
.row
|
||||
.small-12.columns.center
|
||||
%span.small
|
||||
Tip: Square images will work best, preferably at least 300×300px
|
||||
.row.pad-top
|
||||
.small-12.columns
|
||||
.image-select.small-12.columns
|
||||
%label.small-12.columns.button{ for: 'image-select' } Choose a logo image
|
||||
%input#image-select{ type: 'file', hidden: true, 'nv-file-select' => true, uploader: "imageUploader", options: '{ alias: imageStep }' }
|
||||
.row.show-for-large-up
|
||||
.large-12.columns
|
||||
%span#or.large-12.columns
|
||||
OR
|
||||
.row.show-for-large-up
|
||||
.large-12.columns
|
||||
#image-over{ 'nv-file-over' => true, uploader: "imageUploader" }
|
||||
Drag and drop your logo here
|
||||
.small-12.medium-12.large-6.columns
|
||||
.row
|
||||
.small-12.columns.center
|
||||
.row
|
||||
.small-12.columns.center
|
||||
%h4
|
||||
Step 2. Review Your Logo
|
||||
.row
|
||||
.small-12.columns.center
|
||||
%span.small
|
||||
Tip: for best results, your logo should fill the available space
|
||||
.row.pad-top
|
||||
.small-12.columns.center
|
||||
#image-placeholder.logo
|
||||
%img{ ng: { show: "imageSrc()", src: '{{ imageSrc() }}' } }
|
||||
.message{ ng: { hide: "imageSrc()" } }
|
||||
Your logo will appear here for review once uploaded
|
||||
@@ -0,0 +1,39 @@
|
||||
.small-12.medium-12.large-12.columns
|
||||
.row
|
||||
.small-12.columns.center
|
||||
%h4
|
||||
Step 3. Select Promo Image
|
||||
.row
|
||||
.small-12.medium-12.large-5.columns.center
|
||||
.row
|
||||
.small-12.columns.center
|
||||
%span.small
|
||||
Tip: Shown as a banner, preferred size is 1200×260px
|
||||
.row.pad-top
|
||||
.small-12.columns
|
||||
.image-select.small-12.columns
|
||||
%label.small-12.columns.button{ for: 'image-select' } Choose a promo image
|
||||
%input#image-select{ type: 'file', hidden: true, 'nv-file-select' => true, uploader: "imageUploader", options: '{ alias: imageStep }' }
|
||||
.large-2.columns
|
||||
%span#or.horizontal.large-12.columns
|
||||
OR
|
||||
.large-5.columns
|
||||
#image-over{ 'nv-file-over' => true, uploader: "imageUploader" }
|
||||
Drag and drop your promo here
|
||||
.small-12.medium-12.large-12.columns.pad-top
|
||||
.row
|
||||
.small-12.columns.center
|
||||
%h4
|
||||
Step 4. Review Your Promo Banner
|
||||
.row
|
||||
.small-12.columns.center
|
||||
.row
|
||||
.small-12.columns.center
|
||||
%span.small
|
||||
Tip: for best results, your promo image should fill the available space
|
||||
.row.pad-top
|
||||
.small-12.columns.center
|
||||
#image-placeholder.promo
|
||||
%img{ ng: { show: "imageSrc()", src: '{{ imageSrc() }}' } }
|
||||
.message{ ng: { hide: "imageSrc()" } }
|
||||
Your logo will appear here for review once uploaded
|
||||
@@ -6,35 +6,34 @@
|
||||
.small-12.medium-3.large-2.columns.text-right.hide-for-small-only
|
||||
%img{:src => "/assets/potatoes.png"}
|
||||
.small-12.medium-9.large-10.columns
|
||||
%p
|
||||
Your profile gives you an online presence on the
|
||||
%strong Open Food Network,
|
||||
%p
|
||||
Your profile gives you an online presence on the
|
||||
%strong Open Food Network,
|
||||
allowing you to easily connect with potential customers or partners. You can always choose to update your info later, as well as choose to upgrade your Profile to and Online Store, where you can sell products, track orders and receive payments. Creating a profile takes about 5-10 minutes.
|
||||
.row{ 'data-equalizer' => true }
|
||||
.small-12.medium-6.large-6.columns.pad-top{ 'data-equalizer-watch' => true }
|
||||
%h5 You'll need the following:
|
||||
%ul.check-list
|
||||
%li
|
||||
%li
|
||||
Your enterprise address and contact details
|
||||
%li
|
||||
%li
|
||||
Your logo image
|
||||
%li
|
||||
%li
|
||||
A pretty picture for your profile header
|
||||
%li
|
||||
%li
|
||||
Some 'About Us' text
|
||||
|
||||
.small-12.medium-6.large-6.columns{ 'data-equalizer-watch' => true}
|
||||
.highlight-box
|
||||
%h5 Your profile entitles you to:
|
||||
%ul.small-block-grid-1
|
||||
%li
|
||||
%li
|
||||
%i.ofn-i_020-search
|
||||
A searchable listing
|
||||
%li
|
||||
%li
|
||||
%i.ofn-i_040-hub
|
||||
A pin on the OFN map
|
||||
.row
|
||||
.small-12.columns
|
||||
%hr
|
||||
%input.button.primary{ type: "button", value: "Let's get started!", ng: { click: "select('details')" } }
|
||||
|
||||
@@ -30,6 +30,6 @@
|
||||
|
||||
.row.buttons
|
||||
.small-12.columns
|
||||
%input.button.secondary{ type: "button", value: "Back", ng: { click: "select('about')" } }
|
||||
%input.button.secondary{ type: "button", value: "Back", ng: { click: "select('images')" } }
|
||||
|
||||
%input.button.primary{ type: "submit", value: "Continue" }
|
||||
%input.button.primary{ type: "submit", value: "Continue" }
|
||||
|
||||
@@ -80,6 +80,53 @@
|
||||
color: #333
|
||||
@include box-shadow(inset 0 0 1px 0 #fff)
|
||||
|
||||
|
||||
.image-select
|
||||
label
|
||||
font-size: 18px
|
||||
padding: 21px 0px
|
||||
#logo-select
|
||||
display: none
|
||||
|
||||
#image-over
|
||||
font-size: 18px
|
||||
padding: 41px 0px
|
||||
border: 3px dashed #494949
|
||||
text-align: center
|
||||
font-weight: bold
|
||||
color: #494949
|
||||
&.nv-file-over
|
||||
background-color: #78cd91
|
||||
|
||||
#or
|
||||
text-align: center
|
||||
font-weight: bold
|
||||
font-size: 18px
|
||||
padding: 21px 0px
|
||||
&.horizontal
|
||||
padding: 41px 0px
|
||||
|
||||
#image-placeholder
|
||||
font-size: 18px
|
||||
font-weight: bold
|
||||
color: #373737
|
||||
background-color: #e1e1e1
|
||||
text-align: center
|
||||
border: 3px dashed #494949
|
||||
margin-left: auto
|
||||
margin-right: auto
|
||||
&.logo
|
||||
.message
|
||||
padding-top: 6em
|
||||
width: 306px
|
||||
height: 306px
|
||||
&.promo
|
||||
.message
|
||||
padding-top: 4em
|
||||
width: 726px
|
||||
height: 166px
|
||||
|
||||
|
||||
#registration-details
|
||||
#enterprise-types
|
||||
a.panel
|
||||
@@ -112,4 +159,3 @@
|
||||
p
|
||||
clear: both
|
||||
font-size: 0.875rem
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ module Admin
|
||||
before_filter :check_bulk_type, only: :bulk_update
|
||||
before_filter :override_owner, only: :create
|
||||
before_filter :check_owner, only: :update
|
||||
before_filter :check_bulk_owner, only: :bulk_update
|
||||
|
||||
helper 'spree/products'
|
||||
include OrderCyclesHelper
|
||||
@@ -79,11 +80,19 @@ module Admin
|
||||
end
|
||||
|
||||
def check_owner
|
||||
unless spree_current_user == @enterprise.owner || spree_current_user.admin?
|
||||
unless ( spree_current_user == @enterprise.owner ) || spree_current_user.admin?
|
||||
params[:enterprise].delete :owner_id
|
||||
end
|
||||
end
|
||||
|
||||
def check_bulk_owner
|
||||
unless spree_current_user.admin?
|
||||
params[:enterprise_set][:collection_attributes].each do |i, enterprise_params|
|
||||
enterprise_params.delete :owner_id
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Overriding method on Spree's resource controller
|
||||
def location_after_save
|
||||
if params[:enterprise].key? :producer_properties_attributes
|
||||
|
||||
@@ -27,9 +27,9 @@ module Api
|
||||
end
|
||||
|
||||
def update
|
||||
authorize! :update, Enterprise
|
||||
|
||||
@enterprise = Enterprise.find(params[:id])
|
||||
authorize! :update, @enterprise
|
||||
|
||||
if @enterprise.update_attributes(params[:enterprise])
|
||||
render text: @enterprise.id, :status => 200
|
||||
else
|
||||
@@ -37,6 +37,19 @@ module Api
|
||||
end
|
||||
end
|
||||
|
||||
def update_image
|
||||
@enterprise = Enterprise.find(params[:id])
|
||||
authorize! :update, @enterprise
|
||||
|
||||
if params[:logo] && @enterprise.update_attributes( { logo: params[:logo] } )
|
||||
render text: @enterprise.logo.url(:medium), :status => 200
|
||||
elsif params[:promo] && @enterprise.update_attributes( { promo_image: params[:promo] } )
|
||||
render text: @enterprise.promo_image.url(:medium), :status => 200
|
||||
else
|
||||
invalid_resource!(@enterprise)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def override_owner
|
||||
|
||||
@@ -2,7 +2,7 @@ require 'open_food_network/spree_api_key_loader'
|
||||
|
||||
class RegistrationController < BaseController
|
||||
include OpenFoodNetwork::SpreeApiKeyLoader
|
||||
before_filter :load_spree_api_key, only: :index
|
||||
before_filter :load_spree_api_key, only: [:index, :store]
|
||||
before_filter :check_user, except: :authenticate
|
||||
layout 'registration'
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ Spree::Api::ProductsController.class_eval do
|
||||
def bulk_products
|
||||
@products = OpenFoodNetwork::Permissions.new(current_api_user).managed_products.
|
||||
merge(product_scope).
|
||||
order('created_at DESC').
|
||||
ransack(params[:q]).result.
|
||||
page(params[:page]).per(params[:per_page])
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ class Enterprise < ActiveRecord::Base
|
||||
path: 'public/images/enterprises/logos/:id/:style/:basename.:extension'
|
||||
|
||||
has_attached_file :promo_image,
|
||||
styles: { large: "1200x260#", thumb: "100x100>" },
|
||||
styles: { large: "1200x260#", medium: "720x156#", thumb: "100x100>" },
|
||||
url: '/images/enterprises/promo_images/:id/:style/:basename.:extension',
|
||||
path: 'public/images/enterprises/promo_images/:id/:style/:basename.:extension'
|
||||
|
||||
|
||||
@@ -2,12 +2,17 @@ class AbilityDecorator
|
||||
include CanCan::Ability
|
||||
|
||||
def initialize(user)
|
||||
add_base_abilities user if is_new_user? user
|
||||
add_enterprise_management_abilities user if can_manage_enterprises? user
|
||||
add_product_management_abilities user if can_manage_products? user
|
||||
add_relationship_management_abilities user if can_manage_relationships? user
|
||||
end
|
||||
|
||||
|
||||
def is_new_user?(user)
|
||||
user.enterprises.blank?
|
||||
end
|
||||
|
||||
def can_manage_enterprises?(user)
|
||||
user.enterprises.present?
|
||||
end
|
||||
@@ -22,6 +27,9 @@ class AbilityDecorator
|
||||
can_manage_enterprises? user
|
||||
end
|
||||
|
||||
def add_base_abilities(user)
|
||||
can [:create], Enterprise
|
||||
end
|
||||
|
||||
def add_enterprise_management_abilities(user)
|
||||
# Spree performs authorize! on (:create, nil) when creating a new order from admin, and also (:search, nil)
|
||||
@@ -71,7 +79,7 @@ class AbilityDecorator
|
||||
can [:admin, :index, :read, :create, :edit, :update, :fire], Spree::Shipment
|
||||
can [:admin, :index, :read, :create, :edit, :update, :fire], Spree::Adjustment
|
||||
can [:admin, :index, :read, :create, :edit, :update, :fire], Spree::ReturnAuthorization
|
||||
|
||||
|
||||
can [:create], OrderCycle
|
||||
can [:admin, :index, :read, :edit, :update, :bulk_update, :clone], OrderCycle do |order_cycle|
|
||||
user.enterprises.include? order_cycle.coordinator
|
||||
|
||||
@@ -16,7 +16,8 @@
|
||||
%col{style: "width: 5%;"}/
|
||||
- if spree_current_user.admin?
|
||||
%col{style: "width: 12%;"}/
|
||||
%col{style: "width: 18%;"}/
|
||||
- if spree_current_user.admin?
|
||||
%col{style: "width: 18%;"}/
|
||||
%col{style: "width: 25%;"}/
|
||||
%thead
|
||||
%tr{"data-hook" => "enterprises_header"}
|
||||
@@ -25,7 +26,8 @@
|
||||
%th Visible?
|
||||
- if spree_current_user.admin?
|
||||
%th Type
|
||||
%th Owner
|
||||
- if spree_current_user.admin?
|
||||
%th Owner
|
||||
%th
|
||||
%tbody
|
||||
= f.fields_for :collection do |enterprise_form|
|
||||
@@ -41,7 +43,8 @@
|
||||
%td= enterprise_form.check_box :visible
|
||||
- if spree_current_user.admin?
|
||||
%td= enterprise_form.select :type, Enterprise::TYPES, {}, class: 'select2 fullwidth'
|
||||
%td= enterprise_form.select :owner_id, enterprise.users.map{ |e| [ e.email, e.id ] }, {}, class: "select2 fullwidth"
|
||||
- if spree_current_user.admin?
|
||||
%td= enterprise_form.select :owner_id, enterprise.users.map{ |e| [ e.email, e.id ] }, {}, class: "select2 fullwidth"
|
||||
%td{"data-hook" => "admin_users_index_row_actions"}
|
||||
= render 'actions', enterprise: enterprise
|
||||
- if @enterprises.empty?
|
||||
|
||||
@@ -31,6 +31,6 @@
|
||||
|
||||
%section{ role: "main" }
|
||||
= yield
|
||||
|
||||
|
||||
#footer
|
||||
%loading
|
||||
|
||||
Reference in New Issue
Block a user