mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-02-05 22:26:07 +00:00
Merge branch 'master' into email/manager_invite
This commit is contained in:
@@ -640,7 +640,7 @@ GEM
|
||||
shellany (0.0.1)
|
||||
shoulda-matchers (2.8.0)
|
||||
activesupport (>= 3.0.0)
|
||||
skylight (1.5.0)
|
||||
skylight (1.5.1)
|
||||
activesupport (>= 3.0.0)
|
||||
spinjs-rails (1.3)
|
||||
rails (>= 3.1)
|
||||
|
||||
@@ -1,3 +1,14 @@
|
||||
angular.module("ofn.admin", ["ngResource", "ngAnimate", "admin.utils", "admin.indexUtils", "admin.dropdown", "admin.products", "admin.taxons", "infinite-scroll"]).config ($httpProvider) ->
|
||||
angular.module("ofn.admin", [
|
||||
"ngResource",
|
||||
"mm.foundation",
|
||||
"angularFileUpload",
|
||||
"ngAnimate",
|
||||
"admin.utils",
|
||||
"admin.indexUtils",
|
||||
"admin.dropdown",
|
||||
"admin.products",
|
||||
"admin.taxons",
|
||||
"infinite-scroll"
|
||||
]).config ($httpProvider) ->
|
||||
$httpProvider.defaults.headers.common["X-CSRF-Token"] = $("meta[name=csrf-token]").attr("content")
|
||||
$httpProvider.defaults.headers.common["Accept"] = "application/json, text/javascript, */*"
|
||||
|
||||
@@ -51,7 +51,6 @@
|
||||
//= require textAngular.min.js
|
||||
//= require i18n/translations
|
||||
//= require darkswarm/i18n.translate.js
|
||||
//
|
||||
//= require moment
|
||||
//= require moment/en-gb.js
|
||||
//= require moment/es.js
|
||||
@@ -60,5 +59,7 @@
|
||||
//= require moment/nb.js
|
||||
//= require moment/pt-br.js
|
||||
//= require moment/sv.js
|
||||
//= require ../shared/mm-foundation-tpls-0.8.0.min.js
|
||||
//= require angularjs-file-upload
|
||||
|
||||
//= require_tree .
|
||||
|
||||
@@ -12,7 +12,7 @@ angular.module("admin.customers").controller "customersCtrl", ($scope, $q, $filt
|
||||
|
||||
$scope.$watch "shop_id", ->
|
||||
if $scope.shop_id?
|
||||
CurrentShop.shop = $filter('filter')($scope.shops, {id: $scope.shop_id})[0]
|
||||
CurrentShop.shop = $filter('filter')($scope.shops, {id: parseInt($scope.shop_id)}, true)[0]
|
||||
Customers.index({enterprise_id: $scope.shop_id}).then (data) ->
|
||||
pendingChanges.removeAll()
|
||||
$scope.customers_form.$setPristine()
|
||||
|
||||
@@ -5,7 +5,7 @@ angular.module("admin.enterprises")
|
||||
$scope.ShippingMethods = EnterpriseShippingMethods.shippingMethods
|
||||
$scope.navClear = NavigationCheck.clear
|
||||
$scope.menu = SideMenu
|
||||
$scope.newManager = { id: '', email: (t('add_manager')) }
|
||||
$scope.newManager = { id: null, email: (t('add_manager')) }
|
||||
$scope.StatusMessage = StatusMessage
|
||||
|
||||
$scope.$watch 'enterprise_form.$dirty', (newValue) ->
|
||||
@@ -38,17 +38,17 @@ angular.module("admin.enterprises")
|
||||
return
|
||||
for i, user of $scope.Enterprise.users when user.id == manager.id
|
||||
$scope.Enterprise.users.splice i, 1
|
||||
if $scope.enterprise_form?
|
||||
$scope.enterprise_form.$setDirty()
|
||||
$scope.enterprise_form?.$setDirty()
|
||||
|
||||
$scope.addManager = (manager) ->
|
||||
if manager.id? and manager.email?
|
||||
if manager.id? and angular.isNumber(manager.id) and manager.email?
|
||||
manager =
|
||||
id: manager.id
|
||||
email: manager.email
|
||||
confirmed: manager.confirmed
|
||||
if (user for user in $scope.Enterprise.users when user.id == manager.id).length == 0
|
||||
$scope.Enterprise.users.push manager
|
||||
$scope.enterprise_form?.$setDirty()
|
||||
else
|
||||
alert ("#{manager.email}" + " " + t("is_already_manager"))
|
||||
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
angular.module("ofn.admin").controller "ProductImageCtrl", ($scope, ProductImageService) ->
|
||||
$scope.imageUploader = ProductImageService.imageUploader
|
||||
$scope.imagePreview = ProductImageService.imagePreview
|
||||
|
||||
$scope.$watch 'product.image_url', (newValue) ->
|
||||
$scope.imagePreview = newValue if newValue
|
||||
@@ -0,0 +1,6 @@
|
||||
angular.module("ofn.admin").directive "imageModal", ($modal, ProductImageService) ->
|
||||
restrict: 'C'
|
||||
link: (scope, elem, attrs, ctrl) ->
|
||||
elem.on "click", (ev) =>
|
||||
scope.uploadModal = $modal.open(templateUrl: 'admin/modals/image_upload.html', controller: ctrl, scope: scope, windowClass: 'product-image-upload')
|
||||
ProductImageService.configure(scope.product)
|
||||
@@ -0,0 +1,15 @@
|
||||
angular.module("ofn.admin").factory "ProductImageService", (FileUploader, SpreeApiKey) ->
|
||||
new class ProductImageService
|
||||
imagePreview: null
|
||||
|
||||
imageUploader: new FileUploader
|
||||
headers:
|
||||
'X-Spree-Token': SpreeApiKey
|
||||
autoUpload: true
|
||||
|
||||
configure: (product) =>
|
||||
@imageUploader.url = "/api/product_images/#{product.id}"
|
||||
@imagePreview = product.image_url
|
||||
@imageUploader.onSuccessItem = (image, response) =>
|
||||
product.thumb_url = response.thumb_url
|
||||
product.image_url = response.image_url
|
||||
@@ -1,4 +1,5 @@
|
||||
window.Darkswarm = angular.module("Darkswarm", ["ngResource",
|
||||
window.Darkswarm = angular.module("Darkswarm", [
|
||||
'ngResource',
|
||||
'mm.foundation',
|
||||
'LocalStorageModule',
|
||||
'infinite-scroll',
|
||||
@@ -10,7 +11,7 @@ window.Darkswarm = angular.module("Darkswarm", ["ngResource",
|
||||
'duScroll',
|
||||
'angularFileUpload',
|
||||
'angularSlideables'
|
||||
]).config ($httpProvider, $tooltipProvider, $locationProvider, $anchorScrollProvider) ->
|
||||
]).config ($httpProvider, $tooltipProvider, $locationProvider, $anchorScrollProvider) ->
|
||||
$httpProvider.defaults.headers['common']['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, */*"
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
%a.close-reveal-modal{"ng-click" => "$close()"}
|
||||
%i.fa.fa-times-circle{'aria-hidden' => "true"}
|
||||
|
||||
%form#image_upload{ name: 'form', novalidate: true, enctype: 'multipart/form-data', multipart: true, ng: { controller: "ProductImageCtrl" } }
|
||||
%div.image-preview
|
||||
%img.spinner{ src: "/assets/spinning-circles.svg", ng: { hide: "!imageUploader.isUploading" }}
|
||||
%img.preview{ng: {src: "{{imagePreview}}", class: "{'faded': imageUploader.isUploading}"}}
|
||||
|
||||
%label{for: 'image-upload', class: 'button'} #{t('admin.products.bulk_edit.upload_an_image')}
|
||||
%input#image-upload{hidden: true, type: 'file', 'nv-file-select' => true, uploader: "imageUploader"}
|
||||
198
app/assets/stylesheets/admin/modals.css.scss
Normal file
198
app/assets/stylesheets/admin/modals.css.scss
Normal file
@@ -0,0 +1,198 @@
|
||||
.reveal-modal-bg {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background: black;
|
||||
z-index: 1004;
|
||||
display: none;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.reveal-modal, dialog {
|
||||
visibility: hidden;
|
||||
display: none;
|
||||
position: absolute;
|
||||
z-index: 1005;
|
||||
width: 100vw;
|
||||
top: 0;
|
||||
border-radius: 0.4em;
|
||||
border: 0px none;
|
||||
left: 0;
|
||||
background-color: white;
|
||||
padding: 1.25rem;
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.4);
|
||||
padding: 1.875rem;
|
||||
}
|
||||
|
||||
.reveal-modal .column, dialog .column, .reveal-modal .columns, dialog .columns {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.reveal-modal > :first-child, dialog > :first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.reveal-modal > :last-child, dialog > :last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 40.063em) {
|
||||
.reveal-modal, dialog {
|
||||
width: 80%;
|
||||
max-width: 62.5rem;
|
||||
left: 0;
|
||||
right: 0;
|
||||
margin: 0 auto;
|
||||
}
|
||||
}
|
||||
|
||||
.reveal-modal.radius, dialog.radius {
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.reveal-modal.round, dialog.round {
|
||||
border-radius: 1000px;
|
||||
}
|
||||
|
||||
.reveal-modal.collapse, dialog.collapse {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.reveal-modal.full, dialog.full {
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 100%;
|
||||
height: 100vh;
|
||||
min-height: 100vh;
|
||||
max-width: none !important;
|
||||
margin-left: 0 !important;
|
||||
}
|
||||
|
||||
.reveal-modal .close-reveal-modal, dialog .close-reveal-modal {
|
||||
font-size: 2.5rem;
|
||||
line-height: 1;
|
||||
position: absolute;
|
||||
top: 0.625rem;
|
||||
right: 1.375rem;
|
||||
color: #aaaaaa;
|
||||
font-weight: bold;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
dialog::backdrop, dialog + .backdrop {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background: black;
|
||||
background: rgba(0, 0, 0, 0.45);
|
||||
z-index: auto;
|
||||
display: none;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
dialog[open] {
|
||||
display: block;
|
||||
}
|
||||
|
||||
@media print {
|
||||
dialog, .reveal-modal, dialog {
|
||||
display: none;
|
||||
background: white !important;
|
||||
}
|
||||
}
|
||||
|
||||
// ANIMATION CLASSES
|
||||
|
||||
.fade {
|
||||
opacity: 0;
|
||||
-webkit-transition: opacity 0.15s linear;
|
||||
transition: opacity 0.15s linear;
|
||||
}
|
||||
|
||||
.fade.in {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.reveal-modal.fade {
|
||||
-webkit-transition: -webkit-transform 0.2s ease-out;
|
||||
-moz-transition: -moz-transform 0.2s ease-out;
|
||||
-o-transition: -o-transform 0.2s ease-out;
|
||||
transition: transform 0.2s ease-out;
|
||||
-webkit-transform: translate(0, -25%);
|
||||
-ms-transform: translate(0, -25%);
|
||||
transform: translate(0, -25%);
|
||||
}
|
||||
|
||||
.reveal-modal.in {
|
||||
-webkit-transform: translate(0, 0);
|
||||
-ms-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
|
||||
.reveal-modal-bg.fade {
|
||||
filter: alpha(opacity = 0);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.reveal-modal-bg.in {
|
||||
filter: alpha(opacity = 50);
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 40em) {
|
||||
.reveal-modal, dialog {
|
||||
min-height: 100vh;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 40.063em) {
|
||||
.reveal-modal, dialog {
|
||||
top: 6.25rem;
|
||||
}
|
||||
.reveal-modal.tiny, dialog.tiny {
|
||||
width: 30%;
|
||||
max-width: 62.5rem;
|
||||
left: 0;
|
||||
right: 0;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.reveal-modal.small, dialog.small {
|
||||
width: 40%;
|
||||
max-width: 62.5rem;
|
||||
left: 0;
|
||||
right: 0;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.reveal-modal.medium, dialog.medium {
|
||||
width: 60%;
|
||||
max-width: 62.5rem;
|
||||
left: 0;
|
||||
right: 0;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.reveal-modal.large, dialog.large {
|
||||
width: 70%;
|
||||
max-width: 62.5rem;
|
||||
left: 0;
|
||||
right: 0;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.reveal-modal.xlarge, dialog.xlarge {
|
||||
width: 95%;
|
||||
max-width: 62.5rem;
|
||||
left: 0;
|
||||
right: 0;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.reveal-modal.full, dialog.full {
|
||||
width: 100vw;
|
||||
max-width: 62.5rem;
|
||||
left: 0;
|
||||
right: 0;
|
||||
margin: 0 auto;
|
||||
}
|
||||
}
|
||||
@@ -33,6 +33,9 @@ table#listing_products.bulk {
|
||||
margin-bottom: 60px;
|
||||
|
||||
colgroup col {
|
||||
&.image {
|
||||
width: 1%;
|
||||
}
|
||||
&.producer {
|
||||
width: 18%;
|
||||
}
|
||||
@@ -62,6 +65,21 @@ table#listing_products.bulk {
|
||||
}
|
||||
}
|
||||
|
||||
td.image {
|
||||
padding: 10px;
|
||||
text-align: center;
|
||||
img {
|
||||
border: 1px solid transparent;
|
||||
border-radius: 0.4em;
|
||||
}
|
||||
img:hover {
|
||||
opacity: 0.8;
|
||||
cursor: pointer;
|
||||
background-color: #fbfbfb;
|
||||
border: 1px solid #e4e4e4;
|
||||
}
|
||||
}
|
||||
|
||||
td.unit {
|
||||
input, select {
|
||||
width: 100%;
|
||||
@@ -77,3 +95,46 @@ table#listing_products.bulk {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.reveal-modal.product-image-upload {
|
||||
width: 300px;
|
||||
a.close-reveal-modal {
|
||||
font-size: 23px;
|
||||
color: #de6060;
|
||||
right: 0.45rem;
|
||||
top: 0.35rem;
|
||||
:hover {
|
||||
color: #bf4545;
|
||||
}
|
||||
}
|
||||
div.image-preview {
|
||||
//float: left;
|
||||
}
|
||||
label {
|
||||
margin-top: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
form#image_upload {
|
||||
text-align: center;
|
||||
.spinner {
|
||||
width: 160px;
|
||||
height: 65%;
|
||||
position: absolute;
|
||||
//background-color: rgba(255, 255, 255, 0.75);
|
||||
padding: 32px;
|
||||
margin: 0px -80px;
|
||||
left: 50%;
|
||||
z-index: 100;
|
||||
}
|
||||
.preview {
|
||||
width: 240px;
|
||||
}
|
||||
.faded {
|
||||
opacity: 0.25;
|
||||
}
|
||||
.button:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -133,8 +133,6 @@
|
||||
font-size: 0.875rem;
|
||||
margin-bottom: 0.75rem;
|
||||
|
||||
5rem {}
|
||||
|
||||
color: $dark-grey;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
@font-face {
|
||||
font-family: 'OFN';
|
||||
src:url('/OFN.eot?eslsji');
|
||||
src:url('/OFN.eot?#iefixeslsji') format('embedded-opentype'),
|
||||
url('/OFN.woff?eslsji') format('woff'),
|
||||
url('/OFN.ttf?eslsji') format('truetype'),
|
||||
url('/OFN.svg?eslsji#OFN') format('svg');
|
||||
src:url('/OFN-v2.eot?eslsji');
|
||||
src:url('/OFN-v2.eot?#iefixeslsji') format('embedded-opentype'),
|
||||
url('/OFN-v2.woff?eslsji') format('woff'),
|
||||
url('/OFN-v2.ttf?eslsji') format('truetype'),
|
||||
url('/OFN-v2.svg?eslsji#OFN') format('svg');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
19
app/controllers/api/product_images_controller.rb
Normal file
19
app/controllers/api/product_images_controller.rb
Normal file
@@ -0,0 +1,19 @@
|
||||
module Api
|
||||
class ProductImagesController < Spree::Api::BaseController
|
||||
respond_to :json
|
||||
|
||||
def update_product_image
|
||||
@product = Spree::Product.find(params[:product_id])
|
||||
authorize! :update, @product
|
||||
|
||||
if @product.images.first.nil?
|
||||
@image = Spree::Image.create(attachment: params[:file], viewable_id: @product.master.id, viewable_type: 'Spree::Variant')
|
||||
respond_with(@image, status: 201)
|
||||
else
|
||||
@image = @product.images.first
|
||||
@image.update_attributes(attachment: params[:file])
|
||||
respond_with(@image, status: 200)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -7,8 +7,11 @@ Spree::BaseMailer.class_eval do
|
||||
|
||||
protected
|
||||
|
||||
# This method copies the one defined in Spree's mailers. It should be removed
|
||||
# once in Spree v2.0 and Spree's BaseMailer class lands in our codebase.
|
||||
# Then, we'll be able to rely on its #from_address.
|
||||
def from_address
|
||||
Spree::Config[:mails_from] || 'test@example.com'
|
||||
Spree::MailMethod.current.preferred_mails_from
|
||||
end
|
||||
|
||||
def roadie_options
|
||||
|
||||
@@ -4,8 +4,6 @@ Spree::AppConfiguration.class_eval do
|
||||
# we can allow to be modified in the UI by adding appropriate form
|
||||
# elements to existing or new configuration pages.
|
||||
|
||||
preference :mails_from, :string, default: 'no-reply@example.com'
|
||||
|
||||
# Embedded Shopfronts
|
||||
preference :enable_embedded_shopfronts, :boolean, default: false
|
||||
preference :embedded_shopfronts_whitelist, :text, default: nil
|
||||
|
||||
@@ -1,13 +1,21 @@
|
||||
class Api::Admin::ProductSerializer < ActiveModel::Serializer
|
||||
attributes :id, :name, :sku, :variant_unit, :variant_unit_scale, :variant_unit_name, :on_demand, :inherits_properties
|
||||
|
||||
attributes :on_hand, :price, :available_on, :permalink_live, :tax_category_id
|
||||
attributes :on_hand, :price, :available_on, :permalink_live, :tax_category_id, :image_url, :thumb_url
|
||||
|
||||
has_one :supplier, key: :producer_id, embed: :id
|
||||
has_one :primary_taxon, key: :category_id, embed: :id
|
||||
has_many :variants, key: :variants, serializer: Api::Admin::VariantSerializer # embed: ids
|
||||
has_one :master, serializer: Api::Admin::VariantSerializer
|
||||
|
||||
def image_url
|
||||
object.images.present? ? object.images.first.attachment.url(:product) : "/assets/noimage/product.png"
|
||||
end
|
||||
|
||||
def thumb_url
|
||||
object.images.present? ? object.images.first.attachment.url(:mini) : "/assets/noimage/mini.png"
|
||||
end
|
||||
|
||||
def on_hand
|
||||
object.on_hand.nil? ? 0 : object.on_hand.to_f.finite? ? object.on_hand : I18n.t(:on_demand)
|
||||
end
|
||||
|
||||
34
app/services/create_mail_method.rb
Normal file
34
app/services/create_mail_method.rb
Normal file
@@ -0,0 +1,34 @@
|
||||
# Configures Rails to use the specified mail settings. It does so creating
|
||||
# a Spree::MailMethod and applying its configuration.
|
||||
class CreateMailMethod
|
||||
# Constructor
|
||||
#
|
||||
# @param attributes [Hash] MailMethod attributes
|
||||
def initialize(attributes)
|
||||
@attributes = attributes
|
||||
end
|
||||
|
||||
def call
|
||||
persist_attributes
|
||||
initialize_mail_settings
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_reader :attributes
|
||||
|
||||
# Updates the created mail method's attributes with the ones specified
|
||||
def persist_attributes
|
||||
mail_method.update_attributes(attributes)
|
||||
end
|
||||
|
||||
# Creates a new Spree::MailMethod for the current environment
|
||||
def mail_method
|
||||
Spree::MailMethod.create(environment: attributes[:environment])
|
||||
end
|
||||
|
||||
# Makes Spree apply the specified mail settings
|
||||
def initialize_mail_settings
|
||||
Spree::Core::MailSettings.init
|
||||
end
|
||||
end
|
||||
@@ -3,7 +3,6 @@
|
||||
-# So we use onchange and have to get the scope to access the ng controller
|
||||
= form_for [main_app, :admin, @enterprise], html: { name: "enterprise_form",
|
||||
"ng-controller" => 'enterpriseCtrl',
|
||||
'onchange' => 'angular.element(enterprise_form).scope().setFormDirty()',
|
||||
"ng-cloak" => true } do |f|
|
||||
|
||||
%save-bar{ dirty: "enterprise_form.$dirty", persist: "true" }
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
%tr
|
||||
%td
|
||||
- # Ignore this input in the submit
|
||||
= hidden_field_tag :ignored, :new_manager, class: "select2 fullwidth", 'user-select' => 'newManager', 'ng-model' => 'newManager'
|
||||
= hidden_field_tag :ignored, nil, class: "select2 fullwidth", 'user-select' => 'newManager', 'ng-model' => 'newManager'
|
||||
%td.actions
|
||||
%a{ 'ng-click' => 'addManager(newManager)', :class => "icon-plus no-text" }
|
||||
%tr.animate-repeat{ id: "manager-{{manager.id}}", ng: { repeat: 'manager in Enterprise.users' }}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
object @image
|
||||
attributes(*image_attributes)
|
||||
attributes :viewable_type, :viewable_id
|
||||
node( :thumb_url ) { @product.images.first.attachment.url(:mini) }
|
||||
node( :image_url ) { @product.images.first.attachment.url(:product) }
|
||||
@@ -1,5 +1,6 @@
|
||||
%colgroup
|
||||
%col.actions
|
||||
%col.image{ ng: { show: 'columns.image.visible' } }
|
||||
%col.producer{ ng: { show: 'columns.producer.visible' } }
|
||||
%col.sku{ ng: { show: 'columns.sku.visible' } }
|
||||
%col.name{ ng: { show: 'columns.name.visible' } }
|
||||
@@ -21,6 +22,7 @@
|
||||
%th.left-actions
|
||||
%a{ 'ng-click' => 'toggleShowAllVariants()', :style => 'color: red; cursor: pointer' }
|
||||
= t(:expand_all)
|
||||
%th.image{ 'ng-show' => 'columns.image.visible' }
|
||||
%th.producer{ 'ng-show' => 'columns.producer.visible' }=t('admin.producer')
|
||||
%th.sku{ 'ng-show' => 'columns.sku.visible' }=t('admin.sku')
|
||||
%th.name{ 'ng-show' => 'columns.name.visible' }=t('.name')
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
%td.left-actions
|
||||
%a{ 'ofn-toggle-variants' => 'true', :class => "view-variants", 'ng-show' => 'hasVariants(product)' }
|
||||
%a{ :class => "add-variant icon-plus-sign", 'ng-click' => "addVariant(product)", 'ng-show' => "!hasVariants(product) && hasUnit(product)" }
|
||||
%td.image{ 'ng-show' => 'columns.image.visible' }
|
||||
%a{class: 'image-modal'}
|
||||
%img{'ng-src' => '{{ product.thumb_url }}'}
|
||||
%td.producer{ 'ng-show' => 'columns.producer.visible' }
|
||||
%select.select2.fullwidth{ 'ng-model' => 'product.producer_id', :name => 'producer_id', 'ofn-track-product' => 'producer_id', 'ng-options' => 'producer.id as producer.name for producer in producers' }
|
||||
%td.sku{ 'ng-show' => 'columns.sku.visible' }
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
%td.left-actions
|
||||
%a{ :class => "variant-item icon-caret-right", 'ng-hide' => "$last" }
|
||||
%a{ :class => "add-variant icon-plus-sign", 'ng-click' => "addVariant(product)", 'ng-show' => "$last", 'ofn-with-tip' => t('.new_variant') }
|
||||
%td{ 'ng-show' => 'columns.image.visible' }
|
||||
%td{ 'ng-show' => 'columns.producer.visible' }
|
||||
%td{ 'ng-show' => 'columns.sku.visible' }
|
||||
%input{ 'ng-model' => "variant.sku", :name => 'variant_sku', 'ofn-track-variant' => 'sku', :type => 'text' }
|
||||
|
||||
@@ -22,6 +22,13 @@ CURRENCY: AUD
|
||||
# See: config/schedule.rb
|
||||
#SCHEDULE_NOTIFICATIONS: admin@example.com
|
||||
|
||||
# Mail settings
|
||||
MAIL_HOST: 'example.com'
|
||||
MAIL_DOMAIN: 'example.com'
|
||||
MAIL_PORT: 25
|
||||
SMTP_USERNAME: 'ofn'
|
||||
SMTP_PASSWORD: 'f00d'
|
||||
|
||||
# SingleSignOn login for Discourse
|
||||
#
|
||||
# DISCOURSE_SSO_SECRET should be a random string. It must be the same as provided to your Discourse instance.
|
||||
|
||||
@@ -267,6 +267,7 @@ en:
|
||||
phone: Phone
|
||||
price: Price
|
||||
producer: Producer
|
||||
image: Image
|
||||
product: Product
|
||||
quantity: Quantity
|
||||
schedule: Schedule
|
||||
@@ -438,6 +439,15 @@ en:
|
||||
|
||||
products:
|
||||
unit_name_placeholder: 'eg. bunches'
|
||||
bulk_edit:
|
||||
unit: Unit
|
||||
display_as: Display As
|
||||
category: Category
|
||||
tax_category: Tax Category
|
||||
inherits_properties?: Inherits Properties?
|
||||
available_on: Available On
|
||||
av_on: "Av. On"
|
||||
upload_an_image: Upload an image
|
||||
properties:
|
||||
property_name: Property Name
|
||||
inherited_property: Inherited Property
|
||||
|
||||
@@ -1,26 +1,58 @@
|
||||
es:
|
||||
language_name: "Castellano"
|
||||
activerecord:
|
||||
attributes:
|
||||
spree/order:
|
||||
payment_state: Estado del pago
|
||||
shipment_state: Estado del envío
|
||||
completed_at: Completado en
|
||||
number: Número
|
||||
email: E-mail del consumidor
|
||||
errors:
|
||||
models:
|
||||
spree/user:
|
||||
attributes:
|
||||
email:
|
||||
taken: "Ya existe una cuenta con este email. Inicie sesión o restablezca tu contraseña."
|
||||
spree/order:
|
||||
no_card: No hay tarjetas de crédito válidas disponibles
|
||||
activemodel:
|
||||
errors:
|
||||
models:
|
||||
subscription_validator:
|
||||
attributes:
|
||||
subscription_line_items:
|
||||
at_least_one_product: "^Por favor agrega al menos un producto"
|
||||
not_available: "^%{name} no está disponible en el programa seleccionado"
|
||||
ends_at:
|
||||
after_begins_at: "debe ser después comienza en"
|
||||
customer:
|
||||
does_not_belong_to_shop: "no pertenece a %{shop}"
|
||||
schedule:
|
||||
not_coordinated_by_shop: "no está coordinado por %{shop}"
|
||||
payment_method:
|
||||
not_available_to_shop: "no está disponible para %{shop}"
|
||||
invalid_type: "El método debe ser Cash o Stripe"
|
||||
shipping_method:
|
||||
not_available_to_shop: "no está disponible para %{shop}"
|
||||
credit_card:
|
||||
not_available: "no está disponible"
|
||||
blank: "Requerido"
|
||||
devise:
|
||||
confirmations:
|
||||
send_instructions: "Recibirás un correo electrónico con instrucciones sobre cómo confirmar su cuenta en unos minutos."
|
||||
failed_to_send: "Se produjo un error al enviar su correo electrónico de confirmación."
|
||||
resend_confirmation_email: "Reenviar el correo electrónico de confirmación."
|
||||
confirmed: "¡Gracias por confirmar tu correo electrónico! Ahora puedes iniciar sesión."
|
||||
not_confirmed: "Su dirección de correo electrónico no pudo ser confirmada. Tal vez ya has completado este paso?"
|
||||
user_registrations:
|
||||
spree_user:
|
||||
signed_up_but_unconfirmed: "Se ha enviado un mensaje con un enlace de confirmación a tu dirección de correo electrónico. Abre el enlace para activar tu cuenta."
|
||||
failure:
|
||||
invalid: |
|
||||
Correo o contraseña inválidos.
|
||||
¿Has sido invitada? Tal vez necesites crear una cuenta o recuperar tu contraseña.
|
||||
enterprise_confirmations:
|
||||
enterprise:
|
||||
confirmed: Gracias, tu dirección de email ha sido confirmada.
|
||||
not_confirmed: La dirección de correo no pudo ser confirmada. ¿Tal vez ya completó este paso?
|
||||
confirmation_sent: "¡Correo de confirmación enviado!"
|
||||
confirmation_not_sent: "No se pudo enviar un correo de confirmación."
|
||||
Correo o contraseña inválidos.
|
||||
¿Has sido invitada? Tal vez necesites crear una cuenta o recuperar tu contraseña.
|
||||
unconfirmed: "Debes confirmar tu cuenta antes de continuar."
|
||||
enterprise_mailer:
|
||||
confirmation_instructions:
|
||||
subject: "Confirma la dirección de correo electrónico de %{enterprise}"
|
||||
@@ -29,13 +61,48 @@ es:
|
||||
producer_mailer:
|
||||
order_cycle:
|
||||
subject: "Informe Ciclo de Pedido para %{producer}"
|
||||
subscription_mailer:
|
||||
placement_summary_email:
|
||||
subject: Un resumen los pedidos de suscripción recientes
|
||||
greeting: "Hola %{name},"
|
||||
intro: "A continuación se muestra un resumen de los pedidos de suscripción que acaban de realizarse en %{shop}."
|
||||
confirmation_summary_email:
|
||||
subject: Un resumen de los pedidos de suscripción confirmadas recientemente
|
||||
greeting: "Hola %{name},"
|
||||
intro: "A continuación se muestra un resumen de los pedidos de suscripción que acaban de finalizar para %{shop}."
|
||||
summary_overview:
|
||||
total: Se marcaron un total de %{count} suscripciones para ser procesadas automáticamente.
|
||||
success_zero: De estos, ninguno fue procesado.
|
||||
success_some: De estos, %{count} se procesaron con éxito.
|
||||
success_all: Todos fueron procesados con éxito.
|
||||
issues: Los detalles de los problemas encontrados se proporcionan a continuación.
|
||||
summary_detail:
|
||||
no_message_provided: No hay mensajes de error
|
||||
changes:
|
||||
title: Insufficient Stock (%{count} pedidos)
|
||||
explainer: Estos pedidos se procesaron pero no se dispuso de existencias suficientes para algunos artículos solicitados
|
||||
empty:
|
||||
title: Sin stock (%{count} pedidos)
|
||||
explainer: Estas órdenes no se pudieron procesar porque no había existencias disponibles para los artículos solicitados
|
||||
complete:
|
||||
title: Ya procesado (%{count} pedidos)
|
||||
explainer: Estas órdenes ya estaban marcadas como completas y, por lo tanto, no se modificaron
|
||||
processing:
|
||||
title: Error encontrado (%{count} pedidos)
|
||||
explainer: El procesamiento automático de estas órdenes falló debido a un error. El error será mostrado en los casos en que sea posible.
|
||||
failed_payment:
|
||||
title: Error en el pago (%{count} pedidos)
|
||||
explainer: El procesamiento automático del pago de estos pedidos falló debido a un error. El error ha sido listado donde a sido posible.
|
||||
other:
|
||||
title: Otros fallos (%{count} pedidos)
|
||||
explainer: El procesamiento automático de estas órdenes falló por un motivo desconocido. Esto no debería ocurrir, contáctanos si estás viendo esto.
|
||||
home: "OFN"
|
||||
title: Open Food Network
|
||||
welcome_to: 'Bienvenido a '
|
||||
site_meta_description: "Nosotros empezamos desde abajo. Con granjeros y productoras listas para contar sus historias con orgullo y autenticidad. Con distribuidoras listas para conectar gente con productos de forma justa y honesta. Con compradores que creen que mejores decisiones de compras semanales pueden..."
|
||||
search_by_name: Buscar por nombre o barrio...
|
||||
producers_join: Las productoras australianas ahora son bienvenidas a unirse a Open Food Network.
|
||||
charges_sales_tax: ¿Cargos de GST?
|
||||
charges_sales_tax: ¿Cargos de IVA?
|
||||
print_invoice: "Imprimir factura"
|
||||
print_ticket: "Imprimir Ticket"
|
||||
select_ticket_printer: "Seleccionar impresora para los tickets"
|
||||
@@ -47,7 +114,7 @@ es:
|
||||
cancel_order: "Cancelar pedido"
|
||||
confirm_send_invoice: "Una factura para esta orde se envió al cliente. ¿Está seguro que quiere continuar?"
|
||||
confirm_resend_order_confirmation: "¿Estás seguro que quieres reenviar el correo de confirmación del pedido?"
|
||||
must_have_valid_business_number: "%{enterprise_name} debe tener un ABN válido antes de que las facturas se puedan enviar."
|
||||
must_have_valid_business_number: "%{enterprise_name} debe tener un NIF válido antes de que las facturas se puedan enviar."
|
||||
invoice: "Factura"
|
||||
percentage_of_sales: "%{percentage} de ventas"
|
||||
capped_at_cap: "Limitado en %{cap}"
|
||||
@@ -59,6 +126,9 @@ es:
|
||||
say_no: "No"
|
||||
say_yes: "Si"
|
||||
then: Entonces
|
||||
ongoing: En marcha
|
||||
bill_address: Dirección de facturación
|
||||
ship_address: Dirección de envío
|
||||
sort_order_cycles_on_shopfront_by: "Ciclos de Pedidos en Tienda por"
|
||||
required_fields: Los campos obligatorios se indican con un asterisco
|
||||
select_continue: Selecciona y Continua
|
||||
@@ -72,6 +142,7 @@ es:
|
||||
show_all_with_more: "Mostrar todo (%{num} Más)"
|
||||
cancel: Cancelar
|
||||
edit: Editar
|
||||
clone: Duplicar
|
||||
distributors: Distribuidores
|
||||
distribution: Distribución
|
||||
bulk_order_management: Gestión de pedidos en bloque
|
||||
@@ -90,6 +161,7 @@ es:
|
||||
supplier_only: Sólo Proveedor
|
||||
weight: Peso
|
||||
volume: Volumen
|
||||
items: Elementos
|
||||
summary: Resumen
|
||||
detailed: Detallado
|
||||
updated: Actualizado
|
||||
@@ -103,23 +175,39 @@ es:
|
||||
notes: Notas
|
||||
error: Error
|
||||
processing_payment: Procesando el pago...
|
||||
show_only_unfulfilled_orders: Mostrar solo órdenes no finalizadas
|
||||
filter_results: Filtrar resultados
|
||||
quantity: Cantidad
|
||||
pick_up: Recogida
|
||||
copy: Copia
|
||||
actions:
|
||||
create_and_add_another: "Crear y agregar otro"
|
||||
admin:
|
||||
begins_at: Empieza en
|
||||
begins_on: Comienza en
|
||||
customer: Consumidora
|
||||
date: Fecha
|
||||
email: Email
|
||||
ends_at: Termina en
|
||||
ends_on: Finaliza
|
||||
name: Nombre
|
||||
on_hand: Disponibles
|
||||
on_demand: Bajo demanda
|
||||
on_demand?: Bajo demanda?
|
||||
order_cycle: Ciclo de Pedido
|
||||
payment: Pago
|
||||
payment_method: Método de pago
|
||||
phone: Teléfono
|
||||
price: Precio
|
||||
producer: Productora
|
||||
product: Producto
|
||||
quantity: Cantidad
|
||||
schedule: Programación
|
||||
shipping: Envío
|
||||
shipping_method: Método de envío
|
||||
shop: Tienda
|
||||
sku: número de referencia
|
||||
status_state: Provincia
|
||||
tags: Etiquetas
|
||||
variant: Variedad
|
||||
weight: Peso
|
||||
@@ -134,6 +222,10 @@ es:
|
||||
form_invalid: "El formulario contiene campos vacíos o inválidos"
|
||||
clear_filters: Limpiar filtros
|
||||
clear: Limpiar
|
||||
show_more: Mostrar más
|
||||
show_n_more: Mostrar %{num} más
|
||||
choose: "Escoger..."
|
||||
please_select: Por favor selecciona ...
|
||||
columns: Columnas
|
||||
actions: Acciones
|
||||
viewing: "Viendo: %{current_view_name}"
|
||||
@@ -169,6 +261,9 @@ es:
|
||||
embedded_shopfront_settings: "Configuración de la tienda integradaa"
|
||||
enable_embedded_shopfronts: "Habilitar tiendas integradas"
|
||||
embedded_shopfronts_whitelist: "Lista de dominios externos permitidos"
|
||||
number_localization:
|
||||
number_localization_settings: "Number Localization Settings"
|
||||
enable_localized_number: "Usar la logica internacional separador miles/decimales"
|
||||
business_model_configuration:
|
||||
edit:
|
||||
business_model_configuration: "Modelo de Sostenibilidad"
|
||||
@@ -181,7 +276,7 @@ es:
|
||||
fixed_monthly_charge_tip: "Un cargo mensual fijo para todas las organizaciones que se establezcan como una tienda y hayan superado el volumen de negocios facturable mínimo (si se establece)"
|
||||
percentage_of_turnover: "Porcentaje de volumen de ventas"
|
||||
percentage_of_turnover_tip: "Cuando sea mayor que cero (0,0 - 1,0) se aplicará al volumen de ventas total de cada tienda y se agregará a cualquier cargo fijo (a la izquierda) para calcular la factura mensual."
|
||||
monthly_cap_excl_tax: "Límite mensual (excl. GST)"
|
||||
monthly_cap_excl_tax: "Límite mensual (excl. IVA)"
|
||||
monthly_cap_excl_tax_tip: "Cuando sea mayor que cero, este valor se usará como un límite en la cantidad que se cobrará cada mes."
|
||||
tax_rate: "Porcentaje del Impuesto"
|
||||
tax_rate_tip: "Porcentaje del impuesto que se aplica a la factura mensual que las organizaciones cobran por usar el sistema."
|
||||
@@ -258,19 +353,15 @@ es:
|
||||
manages: Gestionan
|
||||
products:
|
||||
unit_name_placeholder: 'ej. manojos'
|
||||
bulk_edit:
|
||||
unit: Unidad
|
||||
display_as: Mostrar como
|
||||
category: Categoría
|
||||
tax_category: Categoría del impuesto
|
||||
inherits_properties?: ¿Propiedades heredadas?
|
||||
available_on: Disponible en
|
||||
av_on: "Disp. en"
|
||||
properties:
|
||||
property_name: Nombre de la Propiedad
|
||||
inherited_property: Propiedad Heredada
|
||||
variants:
|
||||
to_order_tip: "Los artículos hechos según demanda no tienen un nivel de stock, como por ejemplo panes hechos según demanda."
|
||||
product_distributions: "Distribuciones de productos"
|
||||
group_buy_options: "Opciones de compra grupales"
|
||||
seo: "SEO"
|
||||
back_to_products_list: "Volver a la lista de productos"
|
||||
variant_overrides:
|
||||
loading_flash:
|
||||
loading_inventory: CARGANDO INVENTARIO
|
||||
@@ -338,7 +429,7 @@ es:
|
||||
desc_long: Sobre nosotras
|
||||
desc_long_placeholder: Explica a las consumidoras quién eres. Esta información aparecerá en tu perfil público.
|
||||
business_details:
|
||||
abn: ABN
|
||||
abn: NIF
|
||||
abn_placeholder: ej. 99 123 456 789
|
||||
acn: ACN
|
||||
acn_placeholder: ej. 123 456 789
|
||||
@@ -347,8 +438,9 @@ es:
|
||||
contact:
|
||||
name: Nombre
|
||||
name_placeholder: ej. Gustav Plum
|
||||
email_address: Dirección de Email
|
||||
email_address_placeholder: ej. gustav@truffles.com
|
||||
email_address: Dirección de correo electrónico público
|
||||
email_address_placeholder: p.ej. consultas@lacesta.com
|
||||
email_address_tip: "Esta dirección de correo electrónico se mostrará en su perfil público"
|
||||
phone: Teléfono
|
||||
phone_placeholder: ej. 98 7654 3210
|
||||
website: Website
|
||||
@@ -413,9 +505,9 @@ es:
|
||||
create_one_button: Crear una ahora
|
||||
no_method_yet: Todavía no tienes ningún método de envío.
|
||||
shop_preferences:
|
||||
shopfront_requires_login: "¿Visibilidad pública de la tienda?"
|
||||
shopfront_requires_login: "¿Visibilidad de la tienda?"
|
||||
shopfront_requires_login_tip: "Elije si los clientes deben iniciar sesión para ver la tienda o si es visible para todos."
|
||||
shopfront_requires_login_false: "Público"
|
||||
shopfront_requires_login_false: "Pública"
|
||||
shopfront_requires_login_true: "Visible solo para consumidores registrados"
|
||||
recommend_require_login: "Recomendamos requerir a los usuarios que accedan cuando sus pedidos puedan cambiar."
|
||||
allow_guest_orders: "Pedidos de invitados"
|
||||
@@ -426,6 +518,10 @@ es:
|
||||
allow_order_changes_tip: "Permitir a los clientes cambiar sus pedidos mientras que el ciclo de pedido siga abierto."
|
||||
allow_order_changes_false: "Los pedidos efectuados no pueden ser cambiados / cancelados"
|
||||
allow_order_changes_true: "Los clientes pueden cambiar / cancelar pedidos mientras el ciclo de pedido está abierto"
|
||||
enable_subscriptions: "Suscripciones"
|
||||
enable_subscriptions_tip: "¿Habilitar la funcionalidad de suscripciones?"
|
||||
enable_subscriptions_false: "Deshabilitado"
|
||||
enable_subscriptions_true: "Habilitado"
|
||||
shopfront_message: Mensaje de la Tienda
|
||||
shopfront_message_placeholder: >
|
||||
Una explicación opcional para los consumidores que detallan cómo funciona
|
||||
@@ -468,6 +564,8 @@ es:
|
||||
email_confirmation_notice_html: "Falta la confirmación del email. Te hemos enviado un correo de confirmación a %{email}."
|
||||
resend: Reenviar
|
||||
owner: 'Propietaria'
|
||||
contact: "Contacto"
|
||||
contact_tip: "El administrador que recibirá los correos electrónicos de la empresa para pedidos y notificaciones. Debe tener una dirección de correo electrónico confirmada."
|
||||
owner_tip: La principal usaría responsable para esta organización.
|
||||
notifications: Notificaciones
|
||||
notifications_tip: Las Notificaciones sobre los pedidos se enviarán a esta dirección de correo.
|
||||
@@ -475,6 +573,8 @@ es:
|
||||
notifications_note: 'Nota: Una nueva dirección de correo debe ser confirmada. '
|
||||
managers: Gestoras
|
||||
managers_tip: Otras usuarias con permiso para gestionar esta organización.
|
||||
email_confirmed: "Correo electrónico confirmado"
|
||||
email_not_confirmed: "Correo electrónico no confirmado"
|
||||
actions:
|
||||
edit_profile: Editar Perfil
|
||||
properties: Propiedades
|
||||
@@ -565,8 +665,25 @@ es:
|
||||
distributor: Distribuidor
|
||||
products: Productos
|
||||
tags: Etiquetas
|
||||
add_a_tag: Add a tag
|
||||
delivery_details: Detalles de Recogida / Entrega
|
||||
debug_info: Información de Debug
|
||||
index:
|
||||
involving: Involucrando
|
||||
schedule: Horario
|
||||
schedules: Horarios
|
||||
adding_a_new_schedule: Agregar un nuevo horario
|
||||
updating_a_schedule: Actualización de un horario
|
||||
new_schedule: Nuevo horario
|
||||
create_schedule: Crear horario
|
||||
update_schedule: Actualizar horario
|
||||
delete_schedule: Eliminar horario
|
||||
created_schedule: Horario creado
|
||||
updated_schedule: Horario actualizado
|
||||
deleted_schedule: Horario eliminado
|
||||
schedule_name_placeholder: Nombre del horario
|
||||
name_required_error: Por favor ingrese un nombre para este horario
|
||||
no_order_cycles_error: Seleccione al menos un ciclo de pedido (arrastrar y soltar)
|
||||
name_and_timing_form:
|
||||
name: Nombre
|
||||
orders_open: Pedidos abiertos a
|
||||
@@ -583,9 +700,17 @@ es:
|
||||
customer_instructions_placeholder: Notas de la recogida o entrega
|
||||
products: Productos
|
||||
fees: Comisiones
|
||||
destroy_errors:
|
||||
orders_present: Ese ciclo de pedido ha sido seleccionado por un cliente y no puede ser eliminado. Para evitar que los clientes accedan a él, ciérrelo.
|
||||
schedule_present: Ese ciclo de pedido está vinculado a un horario y no puede ser eliminado. Desvincula o elimina el calendario primero.
|
||||
producer_properties:
|
||||
index:
|
||||
title: Propiedades de la Productora
|
||||
proxy_orders:
|
||||
cancel:
|
||||
could_not_cancel_the_order: No se pudo cancelar la orden
|
||||
resume:
|
||||
could_not_resume_the_order: No se pudo reanudar el pedido
|
||||
shared:
|
||||
user_guide_link:
|
||||
user_guide: Manual de Usuario
|
||||
@@ -658,6 +783,67 @@ es:
|
||||
description: Facturas para la importación en Xero
|
||||
packing:
|
||||
name: Informes de empaquetado
|
||||
subscriptions:
|
||||
subscriptions: Suscripciones
|
||||
new: Nueva suscripción
|
||||
create: Crear suscripción
|
||||
index:
|
||||
please_select_a_shop: Por favor seleccione una tienda
|
||||
edit_subscription: Editar suscripción
|
||||
pause_subscription: Pausa Suscripción
|
||||
unpause_subscription: Reanudar suscripción
|
||||
cancel_subscription: Cancelar suscripción
|
||||
setup_explanation:
|
||||
just_a_few_more_steps: 'Solo unos pocos pasos más antes de que pueda comenzar:'
|
||||
enable_subscriptions: "Habilita suscripciones para al menos una de tus tiendas"
|
||||
enable_subscriptions_step_1_html: 1. Vaya a la página %{enterprises_link}, encuentre su tienda y haga clic en "Administrar"
|
||||
enable_subscriptions_step_2: 2. En "Comprar preferencias", habilite la opción Suscripciones
|
||||
set_up_shipping_and_payment_methods_html: Configurar los métodos %{shipping_link} y %{payment_link}
|
||||
set_up_shipping_and_payment_methods_note_html: Tenga en cuenta que solo se pueden usar <br /> métodos de pago en efectivo y Stripe con las suscripciones
|
||||
ensure_at_least_one_customer_html: Asegúrese de que exista al menos un %{customer_link}
|
||||
create_at_least_one_schedule: Crear al menos un horario
|
||||
create_at_least_one_schedule_step_1_html: 1. Vaya a la página %{order_cycles_link}
|
||||
create_at_least_one_schedule_step_2: 2. Crea un ciclo de pedido si aún no lo has hecho
|
||||
create_at_least_one_schedule_step_3: 3. Haga clic en '+ Nuevo horario' y complete el formulario
|
||||
once_you_are_done_you_can_html: Una vez que haya terminado, puede %{reload_this_page_link}
|
||||
reload_this_page: recarga esta página
|
||||
steps:
|
||||
details: 1. Detalles básicos
|
||||
address: 2. Dirección
|
||||
products: 3. Agregue productos
|
||||
review: 4. Revisar y guardar
|
||||
details:
|
||||
details: Detalles
|
||||
invalid_error: Ups! Por favor complete todos los campos requeridos ...
|
||||
allowed_payment_method_types_tip: Solo se pueden usar métodos de pago en efectivo y Stripe en este momento
|
||||
credit_card: Tarjeta de crédito
|
||||
no_cards_available: No hay tarjetas disponibles
|
||||
loading_flash:
|
||||
loading: CARGANDO SUSCRIPCIONES
|
||||
review:
|
||||
details: Detalles
|
||||
address: Dirección
|
||||
products: Productos
|
||||
product_already_in_order: Este producto ya ha sido agregado a la orden. Por favor edite la cantidad directamente.
|
||||
orders:
|
||||
number: Número
|
||||
confirm_edit: ¿Seguro que quieres editar esta orden? Si lo hace, puede ser más difícil sincronizar automáticamente los cambios a la suscripción en el futuro.
|
||||
confirm_cancel_msg: ¿Seguro que quieres cancelar esta suscripción? Esta acción no se puede deshacer.
|
||||
cancel_failure_msg: 'Lo sentimos, ¡la cancelación falló!'
|
||||
confirm_pause_msg: ¿Seguro que quieres pausar esta suscripción?
|
||||
pause_failure_msg: 'Lo sentimos, pausar falló!'
|
||||
confirm_unpause_msg: ¿Seguro que quieres reanudar esta suscripción?
|
||||
unpause_failure_msg: 'Lo sentimos, ¡no se pudo reanudar!'
|
||||
confirm_cancel_open_orders_msg: "Algunas órdenes para esta suscripción están actualmente abiertas. El cliente ya ha sido notificado de que se realizará el pedido. ¿Desea cancelar estos pedidos o conservarlos?"
|
||||
resume_canceled_orders_msg: "Algunos pedidos de esta suscripción se pueden reanudar en este momento. Puede reanudarlos desde el menú desplegable de pedidos."
|
||||
yes_cancel_them: Cancelarlos
|
||||
no_keep_them: Guárdalos
|
||||
yes_i_am_sure: Sí estoy seguro
|
||||
order_update_issues_msg: Algunas órdenes no se pudieron actualizar automáticamente, esto es más probable porque se han editado manualmente. Revise los problemas que se detallan a continuación y realice los ajustes a los pedidos individuales si es necesario.
|
||||
no_results:
|
||||
no_subscriptions: Aún no hay suscripciones ...
|
||||
why_dont_you_add_one: ¿Por qué no agregas una? :)
|
||||
no_matching_subscriptions: No se encontraron suscripciones coincidentes
|
||||
stripe_connect_settings:
|
||||
edit:
|
||||
title: "Stripe Connect"
|
||||
@@ -718,12 +904,12 @@ es:
|
||||
invoice_column_price_with_taxes: "Precio total (Impuestos incl.)"
|
||||
invoice_column_price_without_taxes: "Precio total (Sin Impuestos)"
|
||||
invoice_column_tax_rate: "% Impuestos"
|
||||
invoice_tax_total: "GST Total:"
|
||||
invoice_tax_total: "IVA Total:"
|
||||
tax_invoice: "FACTURA DE IMPUESTOS"
|
||||
tax_total: "Total impuestos (%{rate}):"
|
||||
total_excl_tax: "Total (Sin Impuestos):"
|
||||
total_incl_tax: "Total (Impuestos incl.)"
|
||||
abn: "ABN:"
|
||||
abn: "NIF:"
|
||||
acn: "ACN:"
|
||||
invoice_issued_on: "Factura emitida el:"
|
||||
order_number: "Número de Factura:"
|
||||
@@ -772,13 +958,18 @@ es:
|
||||
no_payment: Sin métodos de pago
|
||||
no_shipping_or_payment: Sin envío ni métodos de pago
|
||||
unconfirmed: sin confirmar
|
||||
days: dias
|
||||
label_shop: "Tienda"
|
||||
label_shops: "Tiendas"
|
||||
label_map: "Mapa"
|
||||
label_producer: "Productora"
|
||||
label_producers: "Productoras"
|
||||
label_groups: "Redes"
|
||||
label_about: "Acerca de"
|
||||
label_connect: "Conectar"
|
||||
label_learn: "Aprender"
|
||||
label_blog: "Blog"
|
||||
label_support: "Soporte"
|
||||
label_shopping: "Tienda"
|
||||
label_login: "Iniciar sesión"
|
||||
label_logout: "Cerrar sesión"
|
||||
@@ -789,7 +980,7 @@ es:
|
||||
label_more: "Mostrar más"
|
||||
label_less: "Mostrar menos"
|
||||
label_notices: "Noticias"
|
||||
items: "artículos"
|
||||
cart_items: "elementos"
|
||||
cart_headline: "Su carrito de compras"
|
||||
total: "Total"
|
||||
cart_updating: "Actualizando el carrito..."
|
||||
@@ -921,12 +1112,12 @@ es:
|
||||
email_community_html: "También tenemos un foro en líea para la discusión comunal relacionada con el programa OFN y los retos únicos del funcionamiento de una organización de alimentación. Lo invitamos a unirse. Estamos evolucionando de forma constante y su aporte en este formo le dará forma a lo que pase luego. %{link}"
|
||||
join_community: "Unirse a la comunidad"
|
||||
email_help: "Si tiene dificultades, revise nuestras preguntas frecuentes, navegue el foro o haga una entrada de con tema de 'Soporte' y ¡alguien le ayudará!"
|
||||
email_confirmation_activate_account: "Antes de que podamos activar su nueva cuenta, necesitamos confirmar su dirección de correo electrónico."
|
||||
email_confirmation_greeting: "Hola, %{contact}!"
|
||||
email_confirmation_profile_created: "¡Se creó un un perfil para %{name} con éxito! Para activar su Perfil necesitamos que confirme esta dirección de correos."
|
||||
email_confirmation_click_link: "Por favor haga clic en el enlace de abajo para confirmar el correo electrónico y continuar configurando su perfil."
|
||||
email_confirmation_link_label: "Confirmar este correo electrónico »"
|
||||
email_confirmation_help_html: "Después de confirmar el correo electrónico puedes acceder a tu cuenta de administración para esta organización. Visita %{link} para encontrar más información sobre las características de %{sitename} y empieza a usar tu perfil o tienda online."
|
||||
email_confirmation_userguide: "Guía de Usuario"
|
||||
email_social: "Conecte con nosotros:"
|
||||
email_contact: "Envíenos un correo electrónico:"
|
||||
email_signoff: "Saludos,"
|
||||
@@ -944,10 +1135,28 @@ es:
|
||||
email_order_summary_price: "Precio"
|
||||
email_order_summary_subtotal: "Subtotal:"
|
||||
email_order_summary_total: "Total:"
|
||||
email_order_summary_includes_tax: "(incluye impuestos):"
|
||||
email_payment_paid: PAGADO
|
||||
email_payment_not_paid: NO PAGADO
|
||||
email_payment_summary: Resumen de pago
|
||||
email_payment_method: "Pagando con:"
|
||||
email_so_placement_intro_html: "Tiene un nuevo pedido con <strong> %{distributor} </strong>"
|
||||
email_so_placement_details_html: "Aquí están los detalles de su pedido para <strong> %{distributor} </strong>:"
|
||||
email_so_placement_changes: "Desafortunadamente, no todos los productos que solicitó estaban disponibles. Las cantidades originales que solicitó aparecen tachadas a continuación."
|
||||
email_so_payment_success_intro_html: "Se ha procesado un pago automático para su pedido desde <strong> %{distributor} </strong>."
|
||||
email_so_placement_explainer_html: "Esta orden se creó automáticamente para usted."
|
||||
email_so_edit_true_html: "Puede <a href='%{order_url}'> realizar cambios </a> hasta que los pedidos se cierren en %{orders_close_at}."
|
||||
email_so_edit_false_html: "Puede <a href='%{order_url}'> ver detalles de este pedido </a> en cualquier momento."
|
||||
email_so_contact_distributor_html: "Si tiene alguna pregunta, puede contactar <strong> %{distributor} </strong> a través de %{email}."
|
||||
email_so_confirmation_intro_html: "Tu pedido con <strong> %{distributor} </strong> ahora está confirmado"
|
||||
email_so_confirmation_explainer_html: "Este pedido fue colocado automáticamente para usted, y ahora ha sido finalizado."
|
||||
email_so_confirmation_details_html: "Aquí encontrará todo lo que necesita saber sobre su pedido en <strong> %{distributor} </strong>:"
|
||||
email_so_empty_intro_html: "Intentamos realizar un nuevo pedido con <strong> %{distributor} </strong>, pero tuvimos algunos problemas ..."
|
||||
email_so_empty_explainer_html: "Lamentablemente, ninguno de los productos que ordenó estaba disponible, por lo que no se realizó ningún pedido. Las cantidades originales que solicitó aparecen tachadas a continuación."
|
||||
email_so_empty_details_html: "Aquí están los detalles del pedido no realizado para <strong> %{distributor} </strong>:"
|
||||
email_so_failed_payment_intro_html: "Intentamos procesar un pago, pero tuvimos algunos problemas ..."
|
||||
email_so_failed_payment_explainer_html: "El pago de su suscripción con <strong> %{distributor} </strong> ha fallado debido a un problema con su tarjeta de crédito. <strong> %{distributor} </strong> ha recibido notificación de este pago fallido."
|
||||
email_so_failed_payment_details_html: "Aquí están los detalles del fallo proporcionados por la pasarela de pago:"
|
||||
email_shipping_delivery_details: Detalles de entrega
|
||||
email_shipping_delivery_time: "Entregar en:"
|
||||
email_shipping_delivery_address: "Dirección de entrega:"
|
||||
@@ -957,9 +1166,8 @@ es:
|
||||
email_special_instructions: "Sus notas:"
|
||||
email_signup_greeting: ¡Hola!
|
||||
email_signup_welcome: "Bienvenido a %{sitename}!"
|
||||
email_signup_login: Su nombre de usuario
|
||||
email_signup_email: Tu correo electrónico para el inicio de sesión es
|
||||
email_signup_shop_html: "Puede empezar a comprar en línea ahora en %{link}."
|
||||
email_signup_confirmed_email: "Gracias por confirmar su email."
|
||||
email_signup_shop_html: "Ahora puedes iniciar sesión en %{link}."
|
||||
email_signup_text: "Gracias por unirte a la red. Si eres un comprador, ¡esperamos presentarte a muchos agricultores, grupos de consumo y deliciosa comida! Si eres una productora o formas parte de una organización de alimentos, estamos emocionados de que formes parte de la red."
|
||||
email_signup_help_html: "Agradecemos todas tus preguntas y feedback; puedes usar el botón de <em>Enviar Feedback</em> en el sitio o escribir un email a %{email}"
|
||||
producer_mail_greeting: "Estimada"
|
||||
@@ -969,7 +1177,7 @@ es:
|
||||
producer_mail_signoff: "Gracias y hasta pronto"
|
||||
shopping_oc_closed: Los pedidos están cerrados
|
||||
shopping_oc_closed_description: "Por favor espere hasta que el próximo ciclo abra (o contactanos de forma directa para ver si podemos aceptar algunos pedidos tardíos)"
|
||||
shopping_oc_last_closed: "El último cilco cerró hace %{distance_of_time}"
|
||||
shopping_oc_last_closed: "El último ciclo cerró hace %{distance_of_time}"
|
||||
shopping_oc_next_open: "El próximo ciclo abrirá en %{distance_of_time}"
|
||||
shopping_tabs_about: "Acerca de %{distributor}"
|
||||
shopping_tabs_contact: "Contacto"
|
||||
@@ -981,6 +1189,8 @@ es:
|
||||
enterprises_next_closing: "Los pedidos se cerrarán"
|
||||
enterprises_ready_for: "Listo para"
|
||||
enterprises_choose: "Escoger cuando quieres tu pedido:"
|
||||
maps_open: "Abierta"
|
||||
maps_closed: "Cerrado"
|
||||
hubs_buy: "Comprar:"
|
||||
hubs_shopping_here: "Comprando aquí"
|
||||
hubs_orders_closed: "Pedidos cerrados"
|
||||
@@ -1053,7 +1263,7 @@ es:
|
||||
groups_signup_contact_text: "Póngase en conta para descubrir qué puede hacer OFN por usted:"
|
||||
groups_signup_detail: "Aquí está el detalle."
|
||||
login_invalid: "Correo electrónico o contraseña inválidos"
|
||||
modal_hubs: "Grupos de Consumo"
|
||||
modal_hubs: "Hubs"
|
||||
modal_hubs_abstract: ¡Nuestros Grupos de Consumo son el punto de contacto entre usted y la gente que hace su comida!
|
||||
modal_hubs_content1: Puede buscar un grupo de consumo conveniente por ubicación o nombre. Algunos grupos de consumo tienen múltiples puntos en loa que puede recoger las compras, y algunos también brindan opciones de entrega a domicilio. Cada Grupo de Consumo es un punto de venta con operaciones de negocio y logística independientes, entonces puede esperar diferencias entre Grupos de Consumo.
|
||||
modal_hubs_content2: Sólo puedes comprar en un grupo de consumo a la vez.
|
||||
@@ -1101,7 +1311,7 @@ es:
|
||||
sell_headline: "¡Consíguelo en Open Food Network!"
|
||||
sell_motivation: "Muestra tus preciosos alimentos."
|
||||
sell_producers: "Productoras"
|
||||
sell_hubs: "Grupos de Consumo"
|
||||
sell_hubs: "Hubs"
|
||||
sell_groups: "Redes"
|
||||
sell_producers_detail: "Crea tu perfil en OFN en cuestión de minutos. En cualquier momento puedes actualizar tu perfil a una tienda en línea y vender tus productos directamente a los consumidores."
|
||||
sell_hubs_detail: "Crea un perfil para tu organización en OFN. En cualquier momento puedes actualizar tu perfil a una tienda de varias productoras."
|
||||
@@ -1122,6 +1332,7 @@ es:
|
||||
shops_signup_help: Estamos listos para ayudar.
|
||||
shops_signup_help_text: Usted necesita un mejor retorno. Usted necesita nuevos compradores y socios de logística. Usted necesita que su historia sea contada a través de ventas al por mayor, al detalle y en la mesa de la cocina.
|
||||
shops_signup_detail: Aquí está el detalle.
|
||||
orders: Pedidos
|
||||
orders_fees: Tarifas...
|
||||
orders_edit_title: Carrito de compras
|
||||
orders_edit_headline: Su carrito de compras
|
||||
@@ -1147,8 +1358,8 @@ es:
|
||||
orders_could_not_cancel: "Lo sentimos, no se pudo cancelar el pedido"
|
||||
orders_cannot_remove_the_final_item: "No se puede quitar el último artículo de un pedido, en su lugar, por favor cancele el pedido."
|
||||
orders_bought_items_notice:
|
||||
one: Un elemento adicional ya está confirmado para este ciclo de pedido
|
||||
other: '%{count} artículos adicionales ya confirmados para este ciclo de pedido'
|
||||
one: "Un elemento adicional ya está confirmado para este ciclo de pedido"
|
||||
other: "%{count} artículos adicionales ya confirmados para este ciclo de pedido"
|
||||
orders_bought_edit_button: Editar artículos confirmados
|
||||
orders_bought_already_confirmed: "* ya confirmados"
|
||||
orders_confirm_cancel: Seguro que desea cancelar este pedido?
|
||||
@@ -1304,14 +1515,13 @@ es:
|
||||
enterprise_about_headline: "¡Seguimos!"
|
||||
enterprise_about_message: "Ahora vamos a profundizar en los detalles acerca de"
|
||||
enterprise_success: "¡Felicidades! %{enterprise} se agregó a Open Food Network "
|
||||
enterprise_registration_exit_message: "Si sale de este asistente en cualquier etapa, debe hacer clic en el enlace de confirmación el el correo electrónico que recibió. Esto lo llevará a la interfaz de administración en la que puede continuar configurando su perfil."
|
||||
enterprise_description: "Descripción corta"
|
||||
enterprise_description_placeholder: "Una frase corta que describa tu organización"
|
||||
enterprise_long_desc: "Descripción larga"
|
||||
enterprise_long_desc_placeholder: "Esta es tu oportunidad de contar la historia de tu organización - ¿qué la hace diferente? Sugerimos mantener la descripción en menos de 600 caracteres o 150 palabras."
|
||||
enterprise_long_desc_length: "%{num} caracteres / recomentdamos hasta 600"
|
||||
enterprise_limit: Límite de la Organización
|
||||
enterprise_abn: "ABN"
|
||||
enterprise_abn: "NIF"
|
||||
enterprise_abn_placeholder: "eg. 99 123 456 789"
|
||||
enterprise_acn: "ACN"
|
||||
enterprise_acn_placeholder: "eg. 123 456 789"
|
||||
@@ -1329,9 +1539,9 @@ es:
|
||||
instagram: "Instagram"
|
||||
instagram_placeholder: "usuario_de_instagram"
|
||||
registration_greeting: "¡Hola!"
|
||||
registration_intro: "Ahora puede crear un perfil para su Productora o Grupo de Consumo"
|
||||
registration_intro: "Ahora puedes crear un perfil para tu Productora o Grupo de Consumo"
|
||||
registration_action: "¡Empecemos!"
|
||||
registration_checklist: "Necesitará"
|
||||
registration_checklist: "Necesitarás"
|
||||
registration_time: "5-10 minutos"
|
||||
registration_enterprise_address: "Dirección de la organización"
|
||||
registration_contact_details: "Detalles de contacto principal"
|
||||
@@ -1345,8 +1555,6 @@ es:
|
||||
registration_finished_headline: "¡Terminado!"
|
||||
registration_finished_thanks: "Gracias por llenar los detalles de %{enterprise}."
|
||||
registration_finished_login: "Puede cambiar o actualizar su negocio en cualquier etapa iniciando sesión en Open Food Network y yendo a Admin."
|
||||
registration_finished_activate: "Activar %{enterprise}."
|
||||
registration_finished_activate_instruction_html: "Hemos enviado un correo de confirmación a <strong>%{email}</strong> si no has activado tu cuenta ya.<br/> Sigue las instrucciones para hacer tu organización visible en Open Food Network."
|
||||
registration_finished_action: "Página de inicio de Open Food Network"
|
||||
registration_contact_name: 'Nombre de contacto'
|
||||
registration_type_headline: "¡Último paso para agregar %{enterprise}!"
|
||||
@@ -1498,7 +1706,7 @@ es:
|
||||
spree_admin_enterprises_producers_total_products: "Total de Productos"
|
||||
spree_admin_enterprises_producers_active_products: "Productos Activos"
|
||||
spree_admin_enterprises_producers_order_cycles: "Productos en OCs"
|
||||
spree_admin_enterprises_tabs_hubs: "Grupos de Consumo"
|
||||
spree_admin_enterprises_tabs_hubs: "HUBS"
|
||||
spree_admin_enterprises_tabs_producers: "PRODUCTORAS"
|
||||
spree_admin_enterprises_producers_manage_products: "GESTIONAR PRODUCTOS"
|
||||
spree_admin_enterprises_any_active_products_text: "No tienes ningún producto activo"
|
||||
@@ -1557,7 +1765,7 @@ es:
|
||||
admin_share_zipcode: "Código Postal"
|
||||
admin_share_country: "País"
|
||||
admin_share_state: "Estado"
|
||||
hub_sidebar_hubs: "Grupos de Consumo"
|
||||
hub_sidebar_hubs: "Hubs"
|
||||
hub_sidebar_none_available: "Ninguno Disponible"
|
||||
hub_sidebar_manage: "Gestionar"
|
||||
hub_sidebar_at_least: "Al menos un grupo debe ser seleccionado"
|
||||
@@ -1571,7 +1779,7 @@ es:
|
||||
report_customers_csv: "Descargar como CSV"
|
||||
report_producers: "Productoras:"
|
||||
report_type: "Tipo de Informe:"
|
||||
report_hubs: "Grupos de Consumo:"
|
||||
report_hubs: "Hubs: "
|
||||
report_payment: "Métodos de Pago:"
|
||||
report_distributor: "Distribuidora:"
|
||||
report_payment_by: 'Pagos por Tipo'
|
||||
@@ -1707,8 +1915,8 @@ es:
|
||||
report_header_temp_controlled: ¿Control de Temperatura?
|
||||
report_header_is_producer: ¿Productora?
|
||||
report_header_not_confirmed: No confirmado
|
||||
report_header_gst_on_income: GST sobre Ingresos
|
||||
report_header_gst_free_income: Ingresos sin GST
|
||||
report_header_gst_on_income: IVA sobre Ingresos
|
||||
report_header_gst_free_income: Ingresos sin IVA
|
||||
report_header_total_untaxable_produce: Total productos sin impuestos
|
||||
report_header_total_taxable_produce: Total productos con impuestos
|
||||
report_header_total_untaxable_fees: Total comisiones sin impuestos
|
||||
@@ -1796,7 +2004,6 @@ es:
|
||||
order_cycles_email_to_producers_notice: 'Los correos electrónicos que se enviarán a las productoras se han puesto en cola para enviarlos.'
|
||||
order_cycles_no_permission_to_coordinate_error: "Ninguna de tus organizaciones tiene permiso para coordinar un ciclo de pedido"
|
||||
order_cycles_no_permission_to_create_error: "No tienes permiso para crear un ciclo de pedido coordinado por esta empresa."
|
||||
order_cycles_no_permission_to_delete_error: "Ese ciclo de pedido ha sido seleccionado por un cliente y no puede eliminarse. Para evitar que los clientes accedan a él, ciérralo."
|
||||
js:
|
||||
saving: 'Guardando...'
|
||||
changes_saved: 'Cambios guardados.'
|
||||
@@ -1815,6 +2022,7 @@ es:
|
||||
resolve_errors: Resuelve los siguientes errores
|
||||
more_items: "+ %{count} Más"
|
||||
admin:
|
||||
enterprise_limit_reached: "Has alcanzado el límite estándar de organizaciones por cuenta. Escriba a %{contact_email} si necesita aumentarlo."
|
||||
modals:
|
||||
got_it: Lo entiendo
|
||||
tag_rule_help:
|
||||
@@ -1973,8 +2181,8 @@ es:
|
||||
could_not_delete_customer: 'No se pudo eliminar al consumidor'
|
||||
product_import:
|
||||
confirmation: |
|
||||
Esto establecerá el nivel de stock a cero en todos los productos para este
|
||||
organización no está presente en el archivo subido.
|
||||
Esto establecerá el nivel de stock a cero en todos los productos para este
|
||||
organización no está presente en el archivo subido.
|
||||
order_cycles:
|
||||
update_success: 'Se ha actualizado su ciclo de pedido.'
|
||||
no_distributors: No hay distribuidores en este ciclo de pedido. Este ciclo de pedido no será visible para las consumidoras hasta que agregues uno. ¿Deseas continuar guardando este ciclo de pedido? '
|
||||
@@ -1984,12 +2192,16 @@ es:
|
||||
customers:
|
||||
select_shop: 'Seleccione primero una tienda'
|
||||
could_not_create: ¡Lo siento! No se pudo crear
|
||||
subscriptions:
|
||||
closes: cierra
|
||||
closed: cerrado
|
||||
producers:
|
||||
signup:
|
||||
start_free_profile: "Empieze con un perfil gratuito, y amplíelo cuando esté preparado!"
|
||||
spree:
|
||||
email: Email
|
||||
account_updated: "Cuenta actualizada!"
|
||||
my_account: "Mi cuenta"
|
||||
admin:
|
||||
orders:
|
||||
invoice:
|
||||
@@ -2041,6 +2253,18 @@ es:
|
||||
title: CARGANDO PRODUCTOS
|
||||
no_products: "Todavía no hay productos. Añade algunos antes"
|
||||
no_results: "No se han encontrado resultados"
|
||||
products_head:
|
||||
name: Nombre
|
||||
unit: Unidad
|
||||
display_as: Mostrar como
|
||||
category: Categoría
|
||||
tax_category: Categoría del impuesto
|
||||
inherits_properties?: Hereda propiedades?
|
||||
available_on: Disponible en
|
||||
av_on: "Disp. en"
|
||||
products_variant:
|
||||
variant_has_n_overrides: "Esta variante tiene %{n} override(s)"
|
||||
new_variant: "Nueva variante"
|
||||
product_name: nombre del producto
|
||||
primary_taxon_form:
|
||||
product_category: categoría del producto
|
||||
@@ -2071,7 +2295,7 @@ es:
|
||||
remember_this_card: ¿Recordar esta tarjeta?
|
||||
date_picker:
|
||||
format: '%Y-%m-%d'
|
||||
js_format: 'aa-mm-dd'
|
||||
js_format: 'yy-mm-dd'
|
||||
inventory: Inventario
|
||||
orders:
|
||||
bought:
|
||||
@@ -2084,7 +2308,6 @@ es:
|
||||
address: dirección
|
||||
adjustments: ajustes
|
||||
awaiting_return: Esperando retorno
|
||||
canceled: cancelado
|
||||
cart: carrito
|
||||
complete: completar
|
||||
confirm: Confirmar
|
||||
@@ -2113,13 +2336,15 @@ es:
|
||||
user_mailer:
|
||||
reset_password_instructions:
|
||||
request_sent_text: |
|
||||
Se ha solicitado el cambio de tu contraseña.
|
||||
Si tu no lo has solicitado simplemente ignora este email.
|
||||
Se ha solicitado el cambio de tu contraseña.
|
||||
Si tu no lo has solicitado simplemente ignora este email.
|
||||
link_text: >
|
||||
Si has solicitado esta acción haz click en el siguiente enlace:
|
||||
issue_text: |
|
||||
Si el enlace no funciona prueba a copiarlo y pegarlo en tu navegador.
|
||||
Si los problemas continúan no dudes en contactarnos.
|
||||
Si el enlace no funciona prueba a copiarlo y pegarlo en tu navegador.
|
||||
Si los problemas continúan no dudes en contactarnos.
|
||||
confirmation_instructions:
|
||||
subject: Por favor, confirma tu cuenta de OFN
|
||||
weight: Peso (en kg)
|
||||
zipcode: Código Postal
|
||||
users:
|
||||
@@ -2133,6 +2358,9 @@ es:
|
||||
settings: Configuración de la cuenta
|
||||
orders:
|
||||
open_orders: Pedidos Abiertos
|
||||
past_orders: Pedidos anteriores
|
||||
transactions:
|
||||
transaction_history: Historial de transacciones
|
||||
open_orders:
|
||||
order: Pedido
|
||||
shop: Tienda
|
||||
@@ -2143,3 +2371,13 @@ es:
|
||||
cancel: Cancelar
|
||||
closed: Cerrado
|
||||
until: Hasta
|
||||
past_orders:
|
||||
order: Pedido
|
||||
shop: Tienda
|
||||
completed_at: Completado en
|
||||
items: Artículos
|
||||
total: Total
|
||||
paid?: ¿Pagado?
|
||||
view: Ver
|
||||
localized_number:
|
||||
invalid_format: tiene un formato invalido. Por favor introduzca un numero.
|
||||
|
||||
@@ -212,6 +212,8 @@ Openfoodnetwork::Application.routes.draw do
|
||||
resource :status do
|
||||
get :job_queue
|
||||
end
|
||||
|
||||
post '/product_images/:product_id', to: 'product_images#update_product_image'
|
||||
end
|
||||
|
||||
namespace :open_food_network do
|
||||
@@ -287,7 +289,6 @@ Spree::Core::Engine.routes.prepend do
|
||||
resources :orders do
|
||||
get :managed, on: :collection
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
namespace :admin do
|
||||
|
||||
21
db/seeds.rb
21
db/seeds.rb
@@ -29,3 +29,24 @@ states.each do |state|
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
def create_mail_method
|
||||
Spree::MailMethod.destroy_all
|
||||
|
||||
CreateMailMethod.new(
|
||||
environment: Rails.env,
|
||||
preferred_enable_mail_delivery: true,
|
||||
preferred_mail_host: ENV.fetch('MAIL_HOST'),
|
||||
preferred_mail_domain: ENV.fetch('MAIL_DOMAIN'),
|
||||
preferred_mail_port: ENV.fetch('MAIL_PORT'),
|
||||
preferred_mail_auth_type: 'login',
|
||||
preferred_smtp_username: ENV.fetch('SMTP_USERNAME'),
|
||||
preferred_smtp_password: ENV.fetch('SMTP_PASSWORD'),
|
||||
preferred_secure_connection_type: 'None',
|
||||
preferred_mails_from: "no-reply@#{ENV.fetch('MAIL_DOMAIN')}",
|
||||
preferred_mail_bcc: '',
|
||||
preferred_intercept_email: ''
|
||||
).call
|
||||
end
|
||||
|
||||
create_mail_method
|
||||
|
||||
@@ -58,6 +58,7 @@ module OpenFoodNetwork
|
||||
def products_bulk_edit_columns
|
||||
node = "spree.admin.products.bulk_edit.products_head"
|
||||
{
|
||||
image: { name: I18n.t("admin.image"), visible: true },
|
||||
producer: { name: I18n.t("admin.producer"), visible: true },
|
||||
sku: { name: I18n.t("admin.sku"), visible: false },
|
||||
name: { name: I18n.t("admin.name"), visible: true },
|
||||
|
||||
@@ -13,11 +13,6 @@ namespace :openfoodnetwork do
|
||||
country = Spree::Country.find_by_iso(ENV.fetch('DEFAULT_COUNTRY_CODE'))
|
||||
state = country.states.first
|
||||
|
||||
Spree::MailMethod.create!(
|
||||
environment: Rails.env,
|
||||
preferred_mails_from: spree_user.email
|
||||
)
|
||||
|
||||
# -- Shipping / payment information
|
||||
unless Spree::Zone.find_by_name 'Australia'
|
||||
puts "[#{task_name}] Seeding shipping / payment information"
|
||||
@@ -210,6 +205,5 @@ namespace :openfoodnetwork do
|
||||
|
||||
spree_user.confirm!
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
|
Before Width: | Height: | Size: 82 KiB After Width: | Height: | Size: 82 KiB |
36
spec/controllers/api/product_images_controller_spec.rb
Normal file
36
spec/controllers/api/product_images_controller_spec.rb
Normal file
@@ -0,0 +1,36 @@
|
||||
require 'spec_helper'
|
||||
require 'spree/api/testing_support/helpers'
|
||||
|
||||
module Api
|
||||
describe ProductImagesController, type: :controller do
|
||||
include AuthenticationWorkflow
|
||||
render_views
|
||||
|
||||
describe "uploading an image" do
|
||||
before do
|
||||
allow(controller).to receive(:spree_current_user) { current_api_user }
|
||||
end
|
||||
|
||||
image_path = File.open(Rails.root.join('app', 'assets', 'images', 'logo-black.png'))
|
||||
let(:image) { Rack::Test::UploadedFile.new(image_path, 'image/png') }
|
||||
let!(:product_without_image) { create(:product) }
|
||||
let!(:product_with_image) { create(:product_with_image) }
|
||||
|
||||
sign_in_as_admin!
|
||||
|
||||
it "saves a new image when none is present" do
|
||||
xhr :post, :update_product_image, product_id: product_without_image.id, file: image, use_route: :product_images
|
||||
|
||||
expect(response.status).to eq 201
|
||||
expect(product_without_image.images.first.id).to eq json_response['id']
|
||||
end
|
||||
|
||||
it "updates an existing product image" do
|
||||
xhr :post, :update_product_image, product_id: product_with_image.id, file: image, use_route: :product_images
|
||||
|
||||
expect(response.status).to eq 200
|
||||
expect(product_with_image.images.first.id).to eq json_response['id']
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -31,12 +31,16 @@ describe UserPasswordsController, type: :controller do
|
||||
end
|
||||
|
||||
it "renders Darkswarm" do
|
||||
Spree::MailMethod.create!(environment: 'test')
|
||||
clear_jobs
|
||||
|
||||
user.send_reset_password_instructions
|
||||
flush_jobs # Send the reset password instructions
|
||||
|
||||
user.reload
|
||||
spree_get :edit, reset_password_token: user.reset_password_token
|
||||
response.should render_template "user_passwords/edit"
|
||||
|
||||
expect(response).to render_template "user_passwords/edit"
|
||||
end
|
||||
|
||||
describe "via ajax" do
|
||||
|
||||
@@ -425,6 +425,13 @@ FactoryGirl.define do
|
||||
stripe_user_id "abc123"
|
||||
stripe_publishable_key "xyz456"
|
||||
end
|
||||
|
||||
factory :product_with_image, parent: :product do
|
||||
after(:create) do |product|
|
||||
image = File.open(Rails.root.join('app', 'assets', 'images', 'logo-white.png'))
|
||||
Spree::Image.create(attachment: image, viewable_id: product.master.id, viewable_type: 'Spree::Variant')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
@@ -744,4 +744,79 @@ feature %q{
|
||||
expect(v.on_hand).to eq 18
|
||||
end
|
||||
end
|
||||
|
||||
describe "Updating product image with new upload interface" do
|
||||
let!(:product) { create(:simple_product, name: "Carrots") }
|
||||
|
||||
it "displays product images and image upload modal" do
|
||||
quick_login_as_admin
|
||||
visit '/admin/products/bulk_edit'
|
||||
|
||||
within "table#listing_products tr#p_#{product.id}" do
|
||||
# Displays product images
|
||||
expect(page).to have_selector "td.image"
|
||||
|
||||
# Shows default image when no image set
|
||||
expect(page).to have_css "img[src='/assets/noimage/mini.png']"
|
||||
@old_thumb_src = page.find("a.image-modal img")['src']
|
||||
|
||||
# Click image
|
||||
page.find("a.image-modal").trigger('click')
|
||||
end
|
||||
|
||||
# Shows upload modal
|
||||
expect(page).to have_selector "div.reveal-modal.product-image-upload"
|
||||
|
||||
within "div.reveal-modal.product-image-upload" do
|
||||
# Shows preview of current image
|
||||
expect(page).to have_css "img.preview"
|
||||
old_image_src = page.find("img.preview")['src']
|
||||
|
||||
# Upload a new image file
|
||||
attach_file 'image-upload', Rails.root.join("public/500.jpg"), visible: false
|
||||
|
||||
# Shows spinner whilst loading
|
||||
expect(page).to have_css "img.spinner", visible: true
|
||||
expect(page).to_not have_css "img.spinner", visible: true
|
||||
|
||||
# Shows new image when finished
|
||||
expect(page).to have_css "img.preview"
|
||||
@new_image_src = page.find("img.preview")['src']
|
||||
expect(old_image_src) != @new_image_src
|
||||
|
||||
# Close modal
|
||||
page.find("a.close-reveal-modal").click
|
||||
end
|
||||
|
||||
expect(page).to_not have_selector "div.reveal-modal.product-image-upload"
|
||||
|
||||
within "table#listing_products tr#p_#{product.id}" do
|
||||
# New thumbnail is shown in image column
|
||||
@new_thumb_src = page.find("a.image-modal img")['src']
|
||||
expect(@old_thumb_src) != @new_thumb_src
|
||||
|
||||
page.find("a.image-modal").trigger('click')
|
||||
end
|
||||
|
||||
expect(page).to have_selector "div.reveal-modal.product-image-upload"
|
||||
|
||||
within "div.reveal-modal.product-image-upload" do
|
||||
# Upload another image file
|
||||
attach_file 'image-upload', Rails.root.join("public/422.jpg"), visible: false
|
||||
|
||||
# Overwrites existing image
|
||||
expect(page).to have_css "img.preview"
|
||||
newer_image_src = page.find("img.preview")['src']
|
||||
expect(@new_image_src) != newer_image_src
|
||||
|
||||
page.find("a.close-reveal-modal").click
|
||||
end
|
||||
|
||||
within "table#listing_products tr#p_#{product.id}" do
|
||||
# Newer thumbnail is shown in image column
|
||||
newer_thumb_src = page.find("a.image-modal img")['src']
|
||||
expect(@new_thumb_src) != newer_thumb_src
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -10,9 +10,10 @@ describe "CustomersCtrl", ->
|
||||
null
|
||||
|
||||
shops = [
|
||||
{ name: "Shop 1", id: 1 }
|
||||
{ name: "Shop 2", id: 2 }
|
||||
{ name: "Shop 3", id: 3 }
|
||||
{ name: "Shop 1", id: 1 },
|
||||
{ name: "Shop 2", id: 12 },
|
||||
{ name: "Shop 3", id: 2 },
|
||||
{ name: "Shop 4", id: 3 }
|
||||
]
|
||||
|
||||
availableCountries = [
|
||||
@@ -39,9 +40,9 @@ describe "CustomersCtrl", ->
|
||||
beforeEach inject (pendingChanges) ->
|
||||
spyOn(pendingChanges, "removeAll")
|
||||
scope.customers_form = jasmine.createSpyObj('customers_form', ['$setPristine'])
|
||||
http.expectGET('/admin/customers.json?enterprise_id=3').respond 200, customers
|
||||
http.expectGET('/admin/customers.json?enterprise_id=2').respond 200, customers
|
||||
scope.$apply ->
|
||||
scope.shop_id = 3
|
||||
scope.shop_id = "2"
|
||||
http.flush()
|
||||
|
||||
it "sets the CurrentShop", inject (CurrentShop) ->
|
||||
@@ -81,7 +82,7 @@ describe "CustomersCtrl", ->
|
||||
{ text: 'three' }
|
||||
]
|
||||
beforeEach ->
|
||||
http.expectGET('/admin/tag_rules/map_by_tag.json?enterprise_id=3').respond 200, tags
|
||||
http.expectGET('/admin/tag_rules/map_by_tag.json?enterprise_id=2').respond 200, tags
|
||||
|
||||
it "retrieves the tag list", ->
|
||||
promise = scope.findTags('')
|
||||
|
||||
@@ -6,14 +6,16 @@ describe EnterpriseMailer do
|
||||
|
||||
before do
|
||||
ActionMailer::Base.deliveries = []
|
||||
Spree::MailMethod.create!(environment: 'test')
|
||||
end
|
||||
|
||||
describe "#welcome" do
|
||||
it "should send a welcome email when given an enterprise" do
|
||||
EnterpriseMailer.welcome(enterprise).deliver
|
||||
expect(ActionMailer::Base.deliveries.count).to eq 1
|
||||
mail = ActionMailer::Base.deliveries.first
|
||||
expect(mail.subject).to eq "#{enterprise.name} is now on #{Spree::Config[:site_name]}"
|
||||
it "sends a welcome email when given an enterprise" do
|
||||
EnterpriseMailer.welcome(enterprise).deliver
|
||||
|
||||
mail = ActionMailer::Base.deliveries.first
|
||||
expect(mail.subject)
|
||||
.to eq "#{enterprise.name} is now on #{Spree::Config[:site_name]}"
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -11,6 +11,8 @@ describe Spree::UserMailer do
|
||||
ActionMailer::Base.delivery_method = :test
|
||||
ActionMailer::Base.perform_deliveries = true
|
||||
ActionMailer::Base.deliveries = []
|
||||
|
||||
Spree::MailMethod.create!(environment: 'test')
|
||||
end
|
||||
|
||||
it "sends an email when given a user" do
|
||||
|
||||
49
spec/services/create_mail_method_spec.rb
Normal file
49
spec/services/create_mail_method_spec.rb
Normal file
@@ -0,0 +1,49 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe CreateMailMethod do
|
||||
describe '#call' do
|
||||
let(:mail_method) { Spree::MailMethod.create(environment: 'test') }
|
||||
let(:mail_settings) { instance_double(Spree::Core::MailSettings) }
|
||||
let(:attributes) do
|
||||
{ preferred_smtp_username: "smtp_username", environment: "test" }
|
||||
end
|
||||
|
||||
before do
|
||||
allow(Spree::MailMethod)
|
||||
.to receive(:create).with(environment: 'test').and_return(mail_method)
|
||||
allow(Spree::Core::MailSettings).to receive(:init) { mail_settings }
|
||||
end
|
||||
|
||||
context 'unit' do
|
||||
before do
|
||||
allow(mail_method).to receive(:update_attributes).with(attributes)
|
||||
end
|
||||
|
||||
it 'creates a new MailMethod' do
|
||||
described_class.new(attributes).call
|
||||
|
||||
expect(Spree::MailMethod)
|
||||
.to have_received(:create).with(environment: 'test') { mail_method }
|
||||
end
|
||||
|
||||
it 'updates the MailMethod' do
|
||||
described_class.new(attributes).call
|
||||
|
||||
expect(mail_method)
|
||||
.to have_received(:update_attributes).with(attributes) { mail_method }
|
||||
end
|
||||
|
||||
it 'initializes the mail settings' do
|
||||
described_class.new(attributes).call
|
||||
expect(Spree::Core::MailSettings).to have_received(:init)
|
||||
end
|
||||
end
|
||||
|
||||
context 'integration' do
|
||||
it 'updates the mail method attributes' do
|
||||
described_class.new(attributes).call
|
||||
expect(mail_method.preferred_smtp_username).to eq('smtp_username')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user