diff --git a/Gemfile b/Gemfile index f8407decdc..45b260c4c8 100644 --- a/Gemfile +++ b/Gemfile @@ -90,6 +90,7 @@ gem 'jquery-rails' gem 'jquery-migrate-rails' gem 'css_splitter' +gem 'ofn-qz', github: 'openfoodfoundation/ofn-qz' group :test, :development do # Pretty printed test output diff --git a/Gemfile.lock b/Gemfile.lock index 824f8a0c04..e03e350866 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -21,6 +21,13 @@ GIT paypal-sdk-merchant (= 1.106.1) spree_core (~> 1.3.4) +GIT + remote: git://github.com/openfoodfoundation/ofn-qz.git + revision: 024680ccea429b2e5428d7b964fa67c52add34ec + specs: + ofn-qz (0.1.0) + railties (~> 3.1) + GIT remote: git://github.com/openfoodfoundation/spree.git revision: a4c439570b77afa50f9e36299811f293232bd281 @@ -694,6 +701,7 @@ DEPENDENCIES momentjs-rails newrelic_rpm nokogiri (>= 1.6.7.1) + ofn-qz! oj paper_trail (~> 3.0.8) paperclip @@ -737,4 +745,4 @@ RUBY VERSION ruby 2.1.5p273 BUNDLED WITH - 1.13.6 + 1.14.3 diff --git a/app/assets/javascripts/templates/admin/links_dropdown.html.haml b/app/assets/javascripts/templates/admin/links_dropdown.html.haml index 6d0ba060e2..13db5f7fb2 100644 --- a/app/assets/javascripts/templates/admin/links_dropdown.html.haml +++ b/app/assets/javascripts/templates/admin/links_dropdown.html.haml @@ -1,7 +1,7 @@ .ofn-drop-down %span %i.icon-check - Actions + = t('admin.actions') %i{ 'ng-class' => "expanded && 'icon-caret-up' || !expanded && 'icon-caret-down'" } %div.menu{ 'ng-show' => "expanded" } %a.menu_item{ 'ng-repeat' => "link in links", href: '{{link.url}}', target: "{{link.target || '_self'}}", data: { method: "{{ link.method || 'get' }}", confirm: "{{link.confirm}}" } } diff --git a/app/assets/javascripts/templates/admin/modals/tag_rule_help.html.haml b/app/assets/javascripts/templates/admin/modals/tag_rule_help.html.haml index 6a0d720a5f..e4f2eda259 100644 --- a/app/assets/javascripts/templates/admin/modals/tag_rule_help.html.haml +++ b/app/assets/javascripts/templates/admin/modals/tag_rule_help.html.haml @@ -1,18 +1,19 @@ #tag-rule-help .margin-bottom-30.text-center - .text-big Tag Rules + .text-big + = t('js.admin.modals.tag_rule_help.title') .margin-bottom-30 - .text-normal Overview - %p Tag rules provide a way to describe which items are visible or otherwise to which customers. Items can be Shipping Methods, Payment Methods, Products and Order Cycles. + .text-normal= t('js.admin.modals.tag_rule_help.overview') + %p= t('js.admin.modals.tag_rule_help.overview_text') .margin-bottom-30 - .text-normal 'By Default...' Rules - %p Default rules allow you to hide items so that they are not visible by default. This behaviour can then be overriden by non-default rules for customers with particular tags. + .text-normal= t('js.admin.modals.tag_rule_help.by_default_rules') + %p= t('js.admin.modals.tag_rule_help.by_default_rules_text') .margin-bottom-30 - .text-normal 'Customers Tagged...' Rules - %p By creating rules related to a specific customer tag, you can override the default behaviour (whether it be to show or to hide items) for customers with the specified tag. + .text-normal= t('js.admin.modals.tag_rule_help.customer_tagged_rules') + %p= t('js.admin.modals.tag_rule_help.customer_tagged_rules_text') .text-center - %input.button.red.icon-plus{ type: 'button', value: 'Got it', ng: { click: 'close()' } } + %input.button.red.icon-plus{ type: 'button', value: t('js.admin.modals.got_it'), ng: { click: 'close()' } } diff --git a/app/assets/javascripts/templates/admin/new_tag_rule_dialog.html.haml b/app/assets/javascripts/templates/admin/new_tag_rule_dialog.html.haml index 653e0d175d..fc746b1335 100644 --- a/app/assets/javascripts/templates/admin/new_tag_rule_dialog.html.haml +++ b/app/assets/javascripts/templates/admin/new_tag_rule_dialog.html.haml @@ -1,6 +1,6 @@ #new-tag-rule-dialog .text-normal.margin-bottom-30.text-center - Select a rule type: + = t('js.admin.new_tag_rule_dialog.select_rule_type') .text-center.margin-bottom-30 -# %select.fullwidth{ 'select2-min-search' => 5, 'ng-model' => 'newRuleType', 'ng-options' => 'ruleType.id as ruleType.name for ruleType in availableRuleTypes' } diff --git a/app/assets/javascripts/templates/admin/panels/enterprise_package.html.haml b/app/assets/javascripts/templates/admin/panels/enterprise_package.html.haml index 7f143d1071..27e1db7365 100644 --- a/app/assets/javascripts/templates/admin/panels/enterprise_package.html.haml +++ b/app/assets/javascripts/templates/admin/panels/enterprise_package.html.haml @@ -2,130 +2,128 @@ .alpha.eight.columns %div{ ng: { if: "!enterprise.is_primary_producer", switch: "enterprise.sells" } } .info{ ng: { switch: { when: "none" } } } - %h3 Hub Profile + %h3= t('js.admin.panels.enterprise_package.hub_profile') %p - %strong COST: ALWAYS FREE + %strong= t('js.admin.panels.enterprise_package.hub_profile_cost') - %p People can find and contact you on the Open Food Network. Your enterprise will be visible on the map, and will be searchable in listings. + %p= t('js.admin.panels.enterprise_package.hub_profile_text1') - %p Having a profile, and making connections within your local food system through the Open Food Network will always be free. + %p= t('js.admin.panels.enterprise_package.hub_profile_text2') .info{ ng: { switch: { when: "any" } } } - %h3 Hub Shop + %h3= t('js.admin.panels.enterprise_package.hub_shop') %p %strong %monthly-pricing-description{ joiner: "comma" } - %p Your enterprise is the backbone of your local food system. You aggregate produce from other enterprises and can sell it through your shop on the Open Food Network. + %p= t('js.admin.panels.enterprise_package.hub_shop_text1') - %p Hubs can take many forms, whether they be a food co-op, a buying group, a veggie-box program, or a local grocery store. + %p= t('js.admin.panels.enterprise_package.hub_shop_text2') - %p If you also want to sell your own products, you will need to switch this enterprise to be a producer. + %p= t('js.admin.panels.enterprise_package.hub_shop_text3') .info{ ng: { switch: { default: true } } } %h3 - Please Choose a Package + = t('js.admin.panels.enterprise_package.choose_package') %i.icon-arrow-right %p - %strong Your enterprise will not be fully activated until a package is selected from the options on the left. + %strong= t('js.admin.panels.enterprise_package.choose_package_text1') %p - Click on an option to see more detailed information about each package, and hit the red SAVE button when you are done! - - + = t('js.admin.panels.enterprise_package.choose_package_text2') %div{ ng: { if: "enterprise.is_primary_producer", switch: "enterprise.sells" } } .info{ ng: { switch: { when: "none" } } } - %h3 Profile Only + %h3= t('js.admin.panels.enterprise_package.profile_only') %p - %strong COST: ALWAYS FREE + %strong= t('js.admin.panels.enterprise_package.profile_only_cost') - %p A profile makes you visible and contactable to others and is a way to share your story. + %p= t('js.admin.panels.enterprise_package.profile_only_text1') - %p If you prefer to focus on producing food, and want to leave the work of selling it to someone else, you won't require a shop on the Open Food Network. + %p= t('js.admin.panels.enterprise_package.profile_only_text2') - %p Add your products to Open Food Network, allowing hubs to stock your products in their stores. + %p= t('js.admin.panels.enterprise_package.profile_only_text3') .info{ ng: { switch: { when: "own" } } } - %h3 Producer Shop + %h3= t('js.admin.panels.enterprise_package.producer_shop') %p %strong %monthly-pricing-description{ joiner: "comma" } - %p Sell your products directly to customers through your very own Open Food Network shopfront. + %p= t('js.admin.panels.enterprise_package.producer_shop_text1') - %p A Producer Shop is for your produce only, if you want to sell produce grown/produced off site, please select 'Producer Hub'. + %p= t('js.admin.panels.enterprise_package.producer_shop_text2') .info{ ng: { switch: { when: "any" } } } - %h3 Producer Hub + %h3= t('js.admin.panels.enterprise_package.producer_hub') %p %strong %monthly-pricing-description{ joiner: "comma" } - %p Your enterprise is the backbone of your local food system. You can sell your own produce as well as produce aggregated from other enterprises through your shopfront on the Open Food Network. + %p= t('js.admin.panels.enterprise_package.producer_hub_text1') - %p Producer Hubs can take many forms, whether they be a CSA, a veggie-box program, or a food co-op with a rooftop garden. + %p= t('js.admin.panels.enterprise_package.producer_hub_text2') - %p The Open Food Network aims to support as many hub models as possible, so no matter your situation, we want to provide the tools you need to run your organisation or local food business. + %p= t('js.admin.panels.enterprise_package.producer_hub_text3') .info{ ng: { switch: { default: true } } } %h3 - Please Choose a Package + = t('js.admin.panels.enterprise_package.choose_package') %i.icon-arrow-right %p - %strong Your producer enterprise will not be fully activated until a package is selected from the options on the left. + %strong= t('js.admin.panels.enterprise_package.choose_package_text1') %p - Click on an option to see more detailed information about each package, and hit the red SAVE button when you are done! + = t('js.admin.panels.enterprise_package.choose_package_text2') .omega.eight.columns{ ng: { switch: "enterprise.is_primary_producer" } } %div{ ng: { switch: { when: "false" } } } %a.button.selector.hub-profile{ ng: { click: "enterprise.owned && (enterprise.sells='none')", class: "{selected: enterprise.sells=='none', disabled: !enterprise.owned}" } } .top - %h3 Profile Only - %p Get a listing - .bottom ALWAYS FREE + %h3= t('js.admin.panels.enterprise_package.profile_only') + %p= t('js.admin.panels.enterprise_package.get_listing') + .bottom= t('js.admin.panels.enterprise_package.always_free') %a.button.selector.hub{ ng: { click: "enterprise.owned && (enterprise.sells='any')", class: "{selected: enterprise.sells=='any', disabled: !enterprise.owned}" } } .top - %h3 Hub Shop - %p Sell produce from others + %h3= t('js.admin.panels.enterprise_package.hub_shop') + %p= t('js.admin.panels.enterprise_package.sell_produce_others') .bottom %monthly-pricing-description{ joiner: "newline" } %div{ ng: { switch: { when: "true" } } } %a.button.selector.producer-profile{ ng: { click: "enterprise.owned && (enterprise.sells='none')", class: "{selected: enterprise.sells=='none', disabled: !enterprise.owned}" } } .top - %h3 Profile Only - %p Get a listing - .bottom ALWAYS FREE + %h3= t('js.admin.panels.enterprise_package.profile_only') + %p= t('js.admin.panels.enterprise_package.get_listing') + .bottom= t('js.admin.panels.enterprise_package.always_free') %a.button.selector.producer-shop{ ng: { click: "enterprise.owned && (enterprise.sells='own')", class: "{selected: enterprise.sells=='own', disabled: !enterprise.owned}" } } .top - %h3 Producer Shop - %p Sell your own produce + %h3= t('js.admin.panels.enterprise_package.producer_shop') + %p= t('js.admin.panels.enterprise_package.sell_own_produce') .bottom %monthly-pricing-description{ joiner: "newline" } %a.button.selector.producer-hub{ ng: { click: "enterprise.owned && (enterprise.sells='any')", class: "{selected: enterprise.sells=='any', disabled: !enterprise.owned}" } } .top - %h3 Producer Hub - %p Sell produce from self and others + %h3= t('js.admin.panels.enterprise_package.producer_hub') + %p= t('js.admin.panels.enterprise_package.sell_both') .bottom %monthly-pricing-description{ joiner: "newline" } %a.button.update.fullwidth{ ng: { show: "enterprise.owned", class: "{disabled: saved() && !saving, saving: saving}", click: "save()" } } %span{ ng: {hide: "saved() || saving" } } - SAVE + = t('js.admin.panels.save') %i.icon-save %span{ ng: {show: "saved() && !saving" } } - SAVED + = t('js.admin.panels.saved') %i.icon-ok-sign %span{ ng: {show: "saving" } } - SAVING + = t('js.admin.panels.saving') %i.icon-refresh diff --git a/app/assets/javascripts/templates/admin/panels/enterprise_producer.html.haml b/app/assets/javascripts/templates/admin/panels/enterprise_producer.html.haml index ea8554892f..b30b15aa63 100644 --- a/app/assets/javascripts/templates/admin/panels/enterprise_producer.html.haml +++ b/app/assets/javascripts/templates/admin/panels/enterprise_producer.html.haml @@ -1,39 +1,37 @@ .row.enterprise_producer_panel{ ng: { controller: 'indexProducerPanelCtrl' } } - .alpha.eight.columns .info{ ng: { show: "enterprise.is_primary_producer==true" } } - %h3 Producer - %p Producers make yummy things to eat &/or drink. You're a producer if you grow it, raise it, brew it, bake it, ferment it, milk it or mould it. - - %p Producers can also perform other functions, such as aggregating food from other enterprises and selling it through a shop on the Open Food Network. + %h3= t('js.admin.panels.enterprise_producer.producer') + %p= t('js.admin.panels.enterprise_producer.producer_text1') + %p= t('js.admin.panels.enterprise_producer.producer_text2') .info{ ng: { show: "enterprise.is_primary_producer==false" } } - %h3 Non-Producer - %p Non-producers do not produce any food themselves, meaning that they cannot create their own products for sale through the Open Food Network. + %h3= t('js.admin.panels.enterprise_producer.non_producer') + %p= t('js.admin.panels.enterprise_producer.non_producer_text1') - %p Instead, non-producers specialise in linking producers to the end eater, whether it be by aggregating, grading, packing, selling or delivering food. + %p= t('js.admin.panels.enterprise_producer.non_producer_text2') .omega.eight.columns %a.button.selector.producer{ ng: { click: 'enterprise.owned && changeToProducer()', class: "{selected: enterprise.is_primary_producer==true, disabled: !enterprise.owned}" } } .top - %h3 PRODUCER - %p Producers of food - .bottom eg. GROWERS, BAKERS, BREWERS, MAKERS + %h3= t('js.admin.panels.enterprise_producer.producer') + %p= t('js.admin.panels.enterprise_producer.producer_desc') + .bottom= t('js.admin.panels.enterprise_producer.producer_example') %a.button.selector.non-producer{ ng: { click: 'enterprise.owned && changeToNonProducer()', class: "{selected: enterprise.is_primary_producer==false, disabled: !enterprise.owned}" } } .top - %h3 Non-Producer - %p All other food enterprises - .bottom eg. Grocery stores, Food co-ops, Buying groups + %h3= t('js.admin.panels.enterprise_producer.non_producer') + %p= t('js.admin.panels.enterprise_producer.non_producer_desc') + .bottom= t('js.admin.panels.enterprise_producer.non_producer_example') %a.button.update.fullwidth{ ng: { show: "enterprise.owned", class: "{disabled: saved() && !saving, saving: saving}", click: "save()" } } %span{ ng: {hide: "saved() || saving" } } - SAVE + = t('js.admin.panels.save') %i.icon-save %span{ ng: {show: "saved() && !saving" } } - SAVED + = t('js.admin.panels.saved') %i.icon-ok-sign %span{ ng: {show: "saving" } } - SAVING + = t('js.admin.panels.saving') %i.icon-refresh diff --git a/app/assets/javascripts/templates/admin/panels/enterprise_status.html.haml b/app/assets/javascripts/templates/admin/panels/enterprise_status.html.haml index 518122774d..305210b3ee 100644 --- a/app/assets/javascripts/templates/admin/panels/enterprise_status.html.haml +++ b/app/assets/javascripts/templates/admin/panels/enterprise_status.html.haml @@ -1,18 +1,17 @@ .row.enterprise_status_panel{ ng: { controller: 'indexStatusPanelCtrl' } } .alpha.omega.sixteen.columns - %h4.status-ok.text-center{ ng: { show: "issues.length == 0 && warnings.length == 0" } } %i.icon-ok-sign - {{ object.name }} is set up and ready to go! + = t('js.admin.panels.enterprise_status.status_title', name: '{{ object.name }}') %table{ ng: { show: "issues.length > 0 || warnings.length > 0" } } %thead %th.severity - Severity + = t('js.admin.panels.enterprise_status.severity') %th.description - Description + = t('js.admin.panels.enterprise_status.description') %th.resolve - Resolve + = t('js.admin.panels.enterprise_status.resolve') %tr{ ng: { repeat: "issue in issues"} } %td.severity %i.icon-warning-sign.issue diff --git a/app/assets/javascripts/templates/admin/show_more.html.haml b/app/assets/javascripts/templates/admin/show_more.html.haml index f9a008993c..0800710927 100644 --- a/app/assets/javascripts/templates/admin/show_more.html.haml +++ b/app/assets/javascripts/templates/admin/show_more.html.haml @@ -1,4 +1,4 @@ %div{ ng: { show: "data.length > limit" } } - %input{ type: 'button', value: 'Show More', ng: { click: 'limit = limit + increment' } } + %input{ type: 'button', value: t(:show_more), ng: { click: 'limit = limit + increment' } } or - %input{ type: 'button', value: "Show All ({{ data.length - limit }} More)", ng: { click: 'limit = data.length' } } + %input{ type: 'button', value: t(:show_more_with_more, num: '{{ data.length - limit }}'), ng: { click: 'limit = data.length' } } diff --git a/app/assets/javascripts/templates/admin/tag_autocomplete.html.haml b/app/assets/javascripts/templates/admin/tag_autocomplete.html.haml index 49ff00ff27..9a6d4e9c26 100644 --- a/app/assets/javascripts/templates/admin/tag_autocomplete.html.haml +++ b/app/assets/javascripts/templates/admin/tag_autocomplete.html.haml @@ -3,9 +3,9 @@ {{$getDisplayText()}} %span.tag-with-rules{ ng: { if: "data.rules == 1" } } — - = t 'admin.has_one_rule' + = t('admin.has_one_rule') %span.tag-with-rules{ ng: { if: "data.rules > 1" } } — - = t 'admin.has_n_rules', { num: '{{data.rules}}' } + = t('admin.has_n_rules', { num: '{{data.rules}}' }) %span{ ng: { if: "!data.rules" } } {{$getDisplayText()}} diff --git a/app/assets/javascripts/templates/out_of_stock.html.haml b/app/assets/javascripts/templates/out_of_stock.html.haml index d894583fcf..5a9662fb6b 100644 --- a/app/assets/javascripts/templates/out_of_stock.html.haml +++ b/app/assets/javascripts/templates/out_of_stock.html.haml @@ -1,13 +1,13 @@ %a.close-reveal-modal{"ng-click" => "$close()"} %i.ofn-i_009-close -%h3 Reduced stock available +%h3= t('js.out_of_stock.reduced_stock_available') -%p While you've been shopping, the stock levels for one or more of the products in your cart have reduced. Here's what's changed: +%p= t('js.out_of_stock.out_of_stock_text') %p{'ng-repeat' => "v in variants"} %em {{ v.name_to_display }} - {{ v.unit_to_display }} %span{'ng-if' => "v.count_on_hand == 0"} - is now out of stock. + = t('js.out_of_stock.now_out_of_stock') %span{'ng-if' => "v.count_on_hand > 0"} - now only has {{ v.count_on_hand }} remaining. + = t('js.out_of_stock.only_n_remainging', num: '{{ v.count_on_hand }}') diff --git a/app/assets/javascripts/templates/registration.html.haml b/app/assets/javascripts/templates/registration.html.haml deleted file mode 100644 index 10a12d712e..0000000000 --- a/app/assets/javascripts/templates/registration.html.haml +++ /dev/null @@ -1,10 +0,0 @@ -%div#registration-modal{"ng-controller" => "RegistrationCtrl"} - %div{ ng: { show: "currentStep() == 'introduction'" } } - %ng-include{ src: "'registration/introduction.html'" } - %div{ ng: { repeat: 'step in steps', show: "currentStep() == step" } } - %ng-include{ src: "'registration/'+ step + '.html'" } - %div{ ng: { show: "currentStep() == 'finished'" } } - %ng-include{ src: "'registration/finished.html'" } - -%a.close-reveal-modal{"ng-click" => "$close()"} - %i.ofn-i_009-close diff --git a/app/assets/javascripts/templates/registration/about.html.haml b/app/assets/javascripts/templates/registration/about.html.haml deleted file mode 100644 index 40d02e3d32..0000000000 --- a/app/assets/javascripts/templates/registration/about.html.haml +++ /dev/null @@ -1,57 +0,0 @@ -.container#registration-about - %ng-include{ src: "'registration/steps.html'" } - .row - .small-12.columns - %header - %h2 {{'enterprise_about_headline' | t}} - %h5 - {{'enterprise_about_message' | t}} - %span{ ng: { class: "{brick: !enterprise.is_primary_producer, turquoise: enterprise.is_primary_producer}" } } - {{ enterprise.name }} - - %form{ name: 'about', novalidate: true, ng: { controller: "RegistrationFormCtrl", submit: "update('images',about)" } } - .row - .small-12.columns - .alert-box.info{ "ofn-inline-alert" => true, ng: { show: "visible" } } - %h6{ "ng-bind" => "'enterprise_success' | t:{enterprise: enterprise.name}" } - %span {{'enterprise_registration_exit_message' | t}} - %a.close{ ng: { click: "close()" } } × - - .small-12.large-8.columns - .row - .small-12.columns - .field - %label{ for: 'enterprise_description' } {{'enterprise_description' | t}}: - %input.chunky{ id: 'enterprise_description', placeholder: "{{'enterprise_description_placeholder' | t}}", ng: { model: 'enterprise.description' } } - .row - .small-12.columns - .field - %label{ for: 'enterprise_long_desc' } {{'enterprise_long_desc' | t}}: - %textarea.chunky{ id: 'enterprise_long_desc', rows: 6, placeholder: "{{'enterprise_long_desc_placeholder' | t}}", ng: { model: 'enterprise.long_description' } } - %small{ "ng-bind" => "'enterprise_long_desc_length' | t:{num: enterprise.long_description.length}" } - .small-12.large-4.columns - .row - .small-12.columns - .field - %label{ for: 'enterprise_abn' } {{'enterprise_abn' | t}}: - %input.chunky{ id: 'enterprise_abn', placeholder: "{{'enterprise_abn_placeholder' | t}}", ng: { model: 'enterprise.abn' } } - .row - .small-12.columns - .field - %label{ for: 'enterprise_acn' } {{'enterprise_acn' | t}}: - %input.chunky{ id: 'enterprise_acn', placeholder: "{{'enterprise_acn_placeholder' | t}}", ng: { model: 'enterprise.acn' } } - .row - .small-12.columns - .field - %label{ for: 'enterprise_charges_sales_tax' }= t(:charges_sales_tax) - %input{ id: 'enterprise_charges_sales_tax_true', type: 'radio', name: 'charges_sales_tax', value: 'true', required: true, ng: { model: 'enterprise.charges_sales_tax' } } - %label{ for: 'enterprise_charges_sales_tax_true' } {{'say_yes' | t}} - %input{ id: 'enterprise_charges_sales_tax_false', type: 'radio', name: 'charges_sales_tax', value: 'false', required: true, ng: { model: 'enterprise.charges_sales_tax' } } - %label{ for: 'enterprise_charges_sales_tax_false' } {{'say_no' | t}} - %span.error.small-12.columns{ ng: { show: "about.charges_sales_tax.$error.required && submitted" } } - {{'enterprise_tax_required' | t}} - - .row.buttons.pad-top - .small-12.columns - %input.button.primary.right{ type: "submit", value: "{{'continue' | t}}" } - diff --git a/app/assets/javascripts/templates/registration/contact.html.haml b/app/assets/javascripts/templates/registration/contact.html.haml deleted file mode 100644 index a22b0677a7..0000000000 --- a/app/assets/javascripts/templates/registration/contact.html.haml +++ /dev/null @@ -1,31 +0,0 @@ -.container#registration-contact - %ng-include{ src: "'registration/steps.html'" } - .row - .small-12.columns - %header - %h2 {{'registration_greeting' | t}} - %h5{ "ng-bind" => "'who_is_managing_enterprise' | t:{enterprise: enterprise.name}" } - - %form{ name: 'contact', novalidate: true, ng: { controller: "RegistrationFormCtrl", submit: "selectIfValid('type',contact)" } } - .row.content - .small-12.medium-12.large-7.columns - .row - .small-12.columns.field - %label{ for: 'enterprise_contact' } {{'enterprise_contact' | t}}: - %input.chunky.small-12.columns{ id: 'enterprise_contact', name: 'contact', required: true, placeholder: "Contact Name", ng: { model: 'enterprise.contact' } } - %span.error.small-12.columns{ ng: { show: "contact.contact.$error.required && submitted" } } - {{'enterprise_contact_required' | t}} - .row - .small-12.columns.field - %label{ for: 'enterprise_email_address' } {{'enterprise_email_address' | t}}: - %input.chunky.small-12.columns{ id: 'enterprise_email_address', name: 'email_address', type: 'email', placeholder: "eg. charlie@thefarm.com", ng: { model: 'enterprise.email_address' } } - .row - .small-12.columns.field - %label{ for: 'enterprise_phone' } {{'enterprise_phone' | t}}: - %input.chunky.small-12.columns{ id: 'enterprise_phone', name: 'phone', placeholder: "eg. (03) 1234 5678", ng: { model: 'enterprise.phone' } } - .small-12.medium-12.large-5.hide-for-small-only - - .row.buttons - .small-12.columns - %input.button.secondary{ type: "button", value: "{{'back' | t}}", ng: { click: "select('details')" } } - %input.button.primary.right{ type: "submit", value: "{{'continue' | t}}" } diff --git a/app/assets/javascripts/templates/registration/details.html.haml b/app/assets/javascripts/templates/registration/details.html.haml deleted file mode 100644 index 6bd3fc02ba..0000000000 --- a/app/assets/javascripts/templates/registration/details.html.haml +++ /dev/null @@ -1,64 +0,0 @@ -.container#registration-details - %ng-include{ src: "'registration/steps.html'" } - .row - .small-12.columns - %header - %h2 {{'registration_detail_headline' | t}} - %h5{ ng: { if: "::enterprise.type != 'own'" } } {{'registration_detail_enterprise' | t}} - %h5{ ng: { if: "::enterprise.type == 'own'" } } {{'registration_detail_producer' | t}} - - %form{ name: 'details', novalidate: true, ng: { controller: "RegistrationFormCtrl", submit: "selectIfValid('contact',details)" } } - - .row - .small-12.medium-9.large-12.columns.end - .field - %label{ for: 'enterprise_name', ng: { if: "::enterprise.type != 'own'" } } {{'registration_detail_name_enterprise' | t}} - %label{ for: 'enterprise_name', ng: { if: "::enterprise.type == 'own'" } } {{'registration_detail_name_producer' | t}} - %input.chunky{ id: 'enterprise_name', name: 'name', placeholder: "{{'registration_detail_name_placeholder' | t}}", required: true, ng: { model: 'enterprise.name' } } - %span.error{ ng: { show: "details.name.$error.required && submitted" } } - {{'registration_detail_name_error' | t}} - - .row - .small-12.medium-9.large-6.columns - .field - %label{ for: 'enterprise_address' } {{'registration_detail_address1' | t}} - %input.chunky{ id: 'enterprise_address', name: 'address1', required: true, placeholder: "{{'registration_detail_address1_placeholder' | t}}", required: true, ng: { model: 'enterprise.address.address1' } } - %span.error{ ng: { show: "details.address1.$error.required && submitted" } } - {{'registration_detail_address1_error' | t}} - .field - %label{ for: 'enterprise_address2' } {{'registration_detail_address2' | t}} - %input.chunky{ id: 'enterprise_address2', name: 'address2', required: false, placeholder: "", required: false, ng: { model: 'enterprise.address.address2' } } - - .small-12.medium-9.large-6.columns.end - .row - .small-12.medium-8.large-8.columns - .field - %label{ for: 'enterprise_city' } {{'registration_detail_suburb' | t}} - %input.chunky{ id: 'enterprise_city', name: 'city', required: true, placeholder: "{{'registration_detail_suburb_placeholder' | t}}", ng: { model: 'enterprise.address.city' } } - %span.error{ ng: { show: "details.city.$error.required && submitted" } } - {{'registration_detail_suburb_error' | t}} - .small-12.medium-4.large-4.columns - .field - %label{ for: 'enterprise_zipcode' } {{'registration_detail_postcode' | t}} - %input.chunky{ id: 'enterprise_zipcode', name: 'zipcode', required: true, placeholder: "{{'registration_detail_postcode_placeholder' | t}}", ng: { model: 'enterprise.address.zipcode' } } - %span.error{ ng: { show: "details.zipcode.$error.required && submitted" } } - {{'registration_detail_postcode_error' | t}} - .row - .small-12.medium-4.large-4.columns - .field - %label{ for: 'enterprise_state' } {{'registration_detail_state' | t}} - %select.chunky{ id: 'enterprise_state', name: 'state', ng: { model: 'enterprise.address.state_id', options: 's.id as s.abbr for s in enterprise.country.states', show: 'countryHasStates()', required: 'countryHasStates()' } } - %span.error{ ng: { show: "details.state.$error.required && submitted" } } - {{'registration_detail_state_error' | t}} - .small-12.medium-8.large-8.columns - .field - %label{ for: 'enterprise_country' } {{'registration_detail_country' | t}} - %select.chunky{ id: 'enterprise_country', name: 'country', required: true, ng: { model: 'enterprise.country', options: 'c as c.name for c in countries' } } - %span.error{ ng: { show: "details.country.$error.required && submitted" } } - {{'registration_detail_country_error' | t}} - - - .row.buttons - .small-12.columns - %hr - %input.button.primary.right{ type: "submit", value: "{{'continue' | t}}" } diff --git a/app/assets/javascripts/templates/registration/finished.html.haml b/app/assets/javascripts/templates/registration/finished.html.haml deleted file mode 100644 index 76403cb1c8..0000000000 --- a/app/assets/javascripts/templates/registration/finished.html.haml +++ /dev/null @@ -1,15 +0,0 @@ -.container#registration-finished - .row - .small-12.columns.pad-top - %header - %h2 {{'registration_finished_headline' | t}} - .panel.callout - %p{ "ng-bind" => "'registration_finished_thanks' | t:{enterprise: enterprise.name}" } - %p {{'registration_finished_login' | t}} - .row - .small-12.columns.text-center - %h4{ "ng-bind" => "'registration_finished_activate' | t:{enterprise: enterprise.name}" } - - %p{ "ng-bind-html" => "'registration_finished_activate_instruction_html' | t:{email: enterprise.email}"} - - %a.button.primary{ type: "button", href: "/" } {{'registration_finished_action' | t}} > diff --git a/app/assets/javascripts/templates/registration/images.html.haml b/app/assets/javascripts/templates/registration/images.html.haml deleted file mode 100644 index 60a1ca602b..0000000000 --- a/app/assets/javascripts/templates/registration/images.html.haml +++ /dev/null @@ -1,22 +0,0 @@ -.container#registration-images{ 'nv-file-drop' => true, uploader: "imageUploader", options:"{ alias: imageStep }", ng: { controller: "EnterpriseImageCtrl" } } - %ng-include{ src: "'registration/steps.html'" } - .row - .small-12.columns - %header - %h2 {{'registration_images_headline' | t}} - %h5 {{'registration_images_description' | t}} - - %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.pad-top{ ng: { if: "imageStep == 'logo'" } } - .small-12.columns - %input.button.secondary{ type: "button", value: "Back", ng: { click: "select('about')" } } - - %input.button.primary.right{ type: "button", value: "Continue", ng: { click: "imageSelect('promo')" } } - - .row.buttons.pad-top{ ng: { if: "imageStep == 'promo'" } } - .small-12.columns - %input.button.secondary{ type: "button", value: "{{'back' | t}}", ng: { click: "imageSelect('logo')" } } - %input.button.primary.right{ type: "submit", value: "{{'continue' | t}}" } diff --git a/app/assets/javascripts/templates/registration/images/logo.html.haml b/app/assets/javascripts/templates/registration/images/logo.html.haml deleted file mode 100644 index 842cbcbe11..0000000000 --- a/app/assets/javascripts/templates/registration/images/logo.html.haml +++ /dev/null @@ -1,45 +0,0 @@ -.small-12.medium-12.large-6.columns - .row - .small-12.columns.center - .row - .small-12.columns.center - %h4 - {{'select_logo' | t}} - .row - .small-12.columns.center - %span.small - {{'logo_tip' | t}} - .row.pad-top - .small-12.columns - .image-select.small-12.columns - %label.small-12.columns.button{ for: 'image-select' } {{'logo_label' | t}} - %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 - {{'action_or' | t}} - .row.show-for-large-up - .large-12.columns - #image-over{ 'nv-file-over' => true, uploader: "imageUploader" } - {{'logo_drag' | t}} -.small-12.medium-12.large-6.columns - .row - .small-12.columns.center - .row - .small-12.columns.center - %h4 - {{'review_logo' | t}} - .row - .small-12.columns.center - %span.small - {{'review_logo_tip' | t}} - .row.pad-top - .small-12.columns.center - #image-placeholder.logo - %img{ ng: { show: "imageSrc() && !imageUploader.isUploading", src: '{{ imageSrc() }}' } } - .message{ ng: { hide: "imageSrc() || imageUploader.isUploading" } } - {{'logo_placeholder' | t}} - .loading{ ng: { hide: "!imageUploader.isUploading" } } - %img.spinner{ src: "/assets/spinning-circles.svg" } - %br/ - {{'uploading' | t}} diff --git a/app/assets/javascripts/templates/registration/images/promo.html.haml b/app/assets/javascripts/templates/registration/images/promo.html.haml deleted file mode 100644 index 342db5c08d..0000000000 --- a/app/assets/javascripts/templates/registration/images/promo.html.haml +++ /dev/null @@ -1,43 +0,0 @@ -.small-12.medium-12.large-12.columns - .row - .small-12.columns.center - %h4 - {{'select_promo_image' | t}} - .row - .small-12.medium-12.large-5.columns.center - .row - .small-12.columns.center - %span.small - {{'promo_image_tip' | t}} - .row.pad-top - .small-12.columns - .image-select.small-12.columns - %label.small-12.columns.button{ for: 'image-select' } {{'promo_image_label' | t}} - %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 - {{'action_or' | t}} - .large-5.columns - #image-over{ 'nv-file-over' => true, uploader: "imageUploader" } - {{'promo_image_drag' | t}} -.small-12.medium-12.large-12.columns.pad-top - .row - .small-12.columns.center - %h4 - {{'review_promo_image' | t}} - .row - .small-12.columns.center - .row - .small-12.columns.center - %span.small - {{'review_promo_image_tip' | t}} - .row.pad-top - .small-12.columns.center - #image-placeholder.promo - %img{ ng: { show: "imageSrc() && !imageUploader.isUploading", src: '{{ imageSrc() }}' } } - .message{ ng: { hide: "imageSrc() || imageUploader.isUploading" } } - {{'promo_image_placeholder' | t}} - .loading{ ng: { hide: "!imageUploader.isUploading" } } - %img.spinner{ src: "/assets/spinning-circles.svg" } - %br/ - {{'uploading' | t}} diff --git a/app/assets/javascripts/templates/registration/introduction.html.haml b/app/assets/javascripts/templates/registration/introduction.html.haml deleted file mode 100644 index c0adb0c357..0000000000 --- a/app/assets/javascripts/templates/registration/introduction.html.haml +++ /dev/null @@ -1,41 +0,0 @@ -.row - .small-12.columns - %header - %h2 {{'registration_greeting' | t}} - %h4 - %small - %i.ofn-i_040-hub - {{'registration_intro' | t}} - .hide-for-large-up - %hr - %input.button.small.primary{ type: "button", value: "{{'registration_action' | t}}", ng: { click: "select('details')" } } - %hr - -.row{ 'data-equalizer' => true } - .small-12.medium-12.large-6.columns.pad-top{ 'data-equalizer-watch' => true } - %h5 {{'registration_checklist' | t}}: - %ul.check-list - %li - {{'registration_time' | t}} - %li - {{'registration_enterprise_address' | t}} - %li - {{'registration_contact_details' | t}} - %li - {{'registration_logo' | t}} - %li - {{'registration_promo_image' | t}} - %li - {{'registration_about_us' | t}} - - .small-9.medium-8.large-5.columns.pad-top.end{ 'data-equalizer-watch' => true} - %h5 - {{'registration_outcome_headline' | t}} - %p{ "ng-bind-html" => "t('registration_outcome1_html')" } - %p {{'registration_outcome2' | t}} - %p {{'registration_outcome3' | t}} - -.row.show-for-large-up - .small-12.columns - %hr - %input.button.primary.right{ type: "button", value: "{{'registration_action' | t}}", ng: { click: "select('details')" } } diff --git a/app/assets/javascripts/templates/registration/limit_reached.html.haml b/app/assets/javascripts/templates/registration/limit_reached.html.haml deleted file mode 100644 index 09e9866fd9..0000000000 --- a/app/assets/javascripts/templates/registration/limit_reached.html.haml +++ /dev/null @@ -1,16 +0,0 @@ -.row - .small-12.columns - %header - %h2 {{'limit_reached_headline' | t}} - %h4 {{'limit_reached_message' | t}} -.row - .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 - {{'limit_reached_text' | t}} - %strong Open Food Network. -.row - .small-12.columns - %hr - %input.button.primary{ type: "button", value: "{{'limit_reached_action' | t}}", ng: { click: "close()" } } diff --git a/app/assets/javascripts/templates/registration/social.html.haml b/app/assets/javascripts/templates/registration/social.html.haml deleted file mode 100644 index ac40ef9c56..0000000000 --- a/app/assets/javascripts/templates/registration/social.html.haml +++ /dev/null @@ -1,45 +0,0 @@ -.container#registration-social - %ng-include{ src: "'registration/steps.html'" } - - .row - .small-12.columns - %header - %h2 {{'enterprise_final_step' | t}} - %h5{ "ng-bind" => "'enterprise_social_text' | t:{enterprise: enterprise.name}" } - - %form{ name: 'social', novalidate: true, ng: { controller: "RegistrationFormCtrl", submit: "update('finished',social)" } } - .row.content - .small-12.large-7.columns - .row - .small-12.columns - .field - %label{ for: 'enterprise_website' } {{'website' | t}}: - %input.chunky{ id: 'enterprise_website', placeholder: "{{'website_placeholder' | t}}", ng: { model: 'enterprise.website' } } - .row - .small-12.columns - .field - %label{ for: 'enterprise_facebook' } {{'facebook' | t}}: - %input.chunky{ id: 'enterprise_facebook', placeholder: "{{'facebook_placeholder' | t}}", ng: { model: 'enterprise.facebook' } } - .row - .small-12.columns - .field - %label{ for: 'enterprise_linkedin' } {{'linkedin' | t}}: - %input.chunky{ id: 'enterprise_linkedin', placeholder: "{{'linkedin_placeholder' | t}}", ng: { model: 'enterprise.linkedin' } } - .small-12.large-5.columns - .row - .small-12.columns - .field - %label{ for: 'enterprise_twitter' } {{'twitter' | t}}: - %input.chunky{ id: 'enterprise_twitter', placeholder: "{{'twitter_placeholder' | t}}", ng: { model: 'enterprise.twitter' } } - .row - .small-12.columns - .field - %label{ for: 'enterprise_instagram' } {{'instagram' | t}}: - %input.chunky{ id: 'enterprise_instagram', placeholder: "{{'instagram_placeholder' | t}}", ng: { model: 'enterprise.instagram' } } - - .row.buttons - .small-12.columns - %input.button.secondary{ type: "button", value: "{{'back' | t}}", ng: { click: "select('images')" } } - %input.button.primary.right{ type: "submit", value: "{{'continue' | t}}" } - - diff --git a/app/assets/javascripts/templates/registration/steps.html.haml b/app/assets/javascripts/templates/registration/steps.html.haml deleted file mode 100644 index 8b420de293..0000000000 --- a/app/assets/javascripts/templates/registration/steps.html.haml +++ /dev/null @@ -1,3 +0,0 @@ -.row#progress-bar - .small-12.medium-2.columns.item{ ng: { repeat: 'step in steps', class: "{active: (currentStep() == step),'show-for-medium-up': (currentStep() != step)}" } } - {{ $index+1 + ". " + step }} diff --git a/app/assets/javascripts/templates/registration/type.html.haml b/app/assets/javascripts/templates/registration/type.html.haml deleted file mode 100644 index 85a81398d7..0000000000 --- a/app/assets/javascripts/templates/registration/type.html.haml +++ /dev/null @@ -1,47 +0,0 @@ -.container#registration-type - - %ng-include{ src: "'registration/steps.html'" } - - .row - .small-12.columns - %header - %h2{ "ng-bind" => "'registration_type_headline' | t:{enterprise: enterprise.name}" } - %h4 - {{'registration_type_question' | t}} - - %form{ name: 'type', novalidate: true, ng: { controller: "RegistrationFormCtrl", submit: "create(type)" } } - .row#enterprise-types{ 'data-equalizer' => true, ng: { if: "::enterprise.type != 'own'" } } - .small-12.columns.field - .row - .small-12.medium-6.large-6.columns{ 'data-equalizer-watch' => true } - %a.btnpanel#producer-panel{ href: "#", ng: { click: "enterprise.is_primary_producer = true", class: "{selected: enterprise.is_primary_producer}" } } - %i.ofn-i_059-producer - %h4 {{'registration_type_producer' | t}} - - .small-12.medium-6.large-6.columns{ 'data-equalizer-watch' => true } - %a.btnpanel#hub-panel{ href: "#", ng: { click: "enterprise.is_primary_producer = false", class: "{selected: enterprise.is_primary_producer == false}" } } - %i.ofn-i_063-hub - %h4 {{'registration_type_no_producer' | t}} - - .row - .small-12.columns - %input.chunky{ id: 'enterprise_is_primary_producer', name: 'is_primary_producer', hidden: true, required: true, ng: { model: 'enterprise.is_primary_producer' } } - %span.error{ ng: { show: "type.is_primary_producer.$error.required && submitted" } } - {{'registration_type_error' | t}} - .row - .small-12.columns - .panel.callout - .left - %i.ofn-i_013-help - - %p {{'registration_type_producer_help' | t}} - .panel.callout - .left - %i.ofn-i_013-help - - %p {{'registration_type_no_producer_help' | t}} - - .row.buttons - .small-12.columns - %input.button.secondary{ type: "button", value: "{{'back' | t}}", ng: { click: "select('contact')" } } - %input.button.primary.right{ type: "submit", value: "{{'create_profile' | t}}" } diff --git a/app/controllers/admin/business_model_configuration_controller.rb b/app/controllers/admin/business_model_configuration_controller.rb index b3c3c67ab8..1cf2ad088d 100644 --- a/app/controllers/admin/business_model_configuration_controller.rb +++ b/app/controllers/admin/business_model_configuration_controller.rb @@ -6,7 +6,8 @@ class Admin::BusinessModelConfigurationController < Spree::Admin::BaseController def update Spree::Config.set(params[:settings]) - flash[:success] = t(:successfully_updated, :resource => t(:business_model_configuration)) + flash[:success] = t(:successfully_updated, + resource: t('admin.business_model_configuration.edit.business_model_configuration')) redirect_to_edit end diff --git a/app/controllers/admin/invoice_settings_controller.rb b/app/controllers/admin/invoice_settings_controller.rb new file mode 100644 index 0000000000..ac65c9860e --- /dev/null +++ b/app/controllers/admin/invoice_settings_controller.rb @@ -0,0 +1,13 @@ +class Admin::InvoiceSettingsController < Spree::Admin::BaseController + + def update + Spree::Config.set(params[:preferences]) + + respond_to do |format| + format.html { + redirect_to main_app.edit_admin_invoice_settings_path + } + end + end + +end diff --git a/app/controllers/spree/admin/orders_controller_decorator.rb b/app/controllers/spree/admin/orders_controller_decorator.rb index b5a2bb4f95..129d4c3308 100644 --- a/app/controllers/spree/admin/orders_controller_decorator.rb +++ b/app/controllers/spree/admin/orders_controller_decorator.rb @@ -77,7 +77,8 @@ Spree::Admin::OrdersController.class_eval do end def invoice - pdf = render_to_string pdf: "invoice-#{@order.number}.pdf", template: "spree/admin/orders/invoice", formats: [:html], encoding: "UTF-8" + template = if Spree::Config.invoice_style2? then "spree/admin/orders/invoice2" else "spree/admin/orders/invoice" end + pdf = render_to_string pdf: "invoice-#{@order.number}.pdf", template: template, formats: [:html], encoding: "UTF-8" Spree::OrderMailer.invoice_email(@order.id, pdf).deliver flash[:success] = t(:invoice_email_sent) @@ -85,7 +86,12 @@ Spree::Admin::OrdersController.class_eval do end def print - render pdf: "invoice-#{@order.number}", template: "spree/admin/orders/invoice", encoding: "UTF-8" + template = if Spree::Config.invoice_style2? then "spree/admin/orders/invoice2" else "spree/admin/orders/invoice" end + render pdf: "invoice-#{@order.number}", template: template, encoding: "UTF-8" + end + + def print_ticket + render template: "spree/admin/orders/ticket", layout: false end def update_distribution_charge diff --git a/app/controllers/spree/admin/reports_controller_decorator.rb b/app/controllers/spree/admin/reports_controller_decorator.rb index 8441b2d596..8a5a5fa2b2 100644 --- a/app/controllers/spree/admin/reports_controller_decorator.rb +++ b/app/controllers/spree/admin/reports_controller_decorator.rb @@ -38,6 +38,10 @@ Spree::Admin::ReportsController.class_eval do ["Payment Methods Report", :payment_methods], ["Delivery Report", :delivery] ], + sales_tax: [ + ["Tax Types", :tax_types], + ["Tax Rates", :tax_rates] + ], packing: [ ["Pack By Customer", :pack_by_customer], ["Pack By Supplier", :pack_by_supplier] @@ -59,6 +63,8 @@ Spree::Admin::ReportsController.class_eval do render_to_string(partial: 'order_cycle_management_description', layout: false, locals: {report_types: REPORT_TYPES[:order_cycle_management]}).html_safe @reports[:packing][:description] = render_to_string(partial: 'packing_description', layout: false, locals: {report_types: REPORT_TYPES[:packing]}).html_safe + @reports[:sales_tax][:description] = + render_to_string(partial: 'sales_tax_description', layout: false, locals: {report_types: REPORT_TYPES[:sales_tax]}).html_safe } } } @@ -159,6 +165,7 @@ Spree::Admin::ReportsController.class_eval do def sales_tax prepare_date_params params @distributors = Enterprise.is_distributor.managed_by(spree_current_user) + @report_type = params[:report_type] @report = OpenFoodNetwork::SalesTaxReport.new spree_current_user, params @@ -320,8 +327,7 @@ Spree::Admin::ReportsController.class_eval do :order_cycle_management => {:name => "Order Cycle Management", :description => ''}, :sales_tax => { :name => "Sales Tax", :description => "Sales Tax For Orders" }, :xero_invoices => { :name => "Xero Invoices", :description => 'Invoices for import into Xero' }, - :packing => { :name => "Packing Reports", :description => '' }, - :sales_tax => { :name => "Sales Tax", :description => "Sales Tax For Orders" } + :packing => { :name => "Packing Reports", :description => '' } } # Return only reports the user is authorized to view. reports.select { |action| can? action, :report } diff --git a/app/helpers/checkout_helper.rb b/app/helpers/checkout_helper.rb index 57cbfd7b73..f55a619f2b 100644 --- a/app/helpers/checkout_helper.rb +++ b/app/helpers/checkout_helper.rb @@ -43,6 +43,29 @@ module CheckoutHelper Spree::Money.new order.total_tax, currency: order.currency end + def display_checkout_taxes_hash(order) + order.tax_adjustment_totals.each_with_object(Hash.new) do |(tax_rate, tax_amount), hash| + hash[number_to_percentage(tax_rate * 100, :precision => 1)] = Spree::Money.new tax_amount, currency: order.currency + end + end + + def display_line_item_tax_rates(line_item) + line_item.tax_rates.map { |tr| number_to_percentage(tr.amount * 100, :precision => 1) }.join(", ") + end + + def display_adjustment_tax_rates(adjustment) + tax_rate = (adjustment.included_tax / (adjustment.amount - adjustment.included_tax)).round(2) + if tax_rate == 0 || tax_rate.infinite? + "" + else + number_to_percentage(tax_rate * 100, :precision => 1) + end + end + + def display_adjustment_amount(adjustment) + Spree::Money.new(adjustment.amount, { :currency => adjustment.currency }) + end + def display_checkout_total_less_tax(order) Spree::Money.new order.total - order.total_tax, currency: order.currency end diff --git a/app/helpers/spree/admin/orders_helper_decorator.rb b/app/helpers/spree/admin/orders_helper_decorator.rb index 23443cc400..94a850bb7f 100644 --- a/app/helpers/spree/admin/orders_helper_decorator.rb +++ b/app/helpers/spree/admin/orders_helper_decorator.rb @@ -13,6 +13,10 @@ module Spree links << { name: t(:send_invoice), url: "#", icon: 'icon-email', confirm: t(:must_have_valid_business_number, enterprise_name: order.distributor.name) } end links << { name: t(:print_invoice), url: print_admin_order_path(order), icon: 'icon-print', target: "_blank" } + if Spree::Config.enable_receipt_printing? + links << { name: t(:print_ticket), url: print_ticket_admin_order_path(order), icon: 'icon-print', target: "_blank" } + links << { name: t(:select_ticket_printer), url: "#{print_ticket_admin_order_path(order)}#select-printer", icon: 'icon-print', target: "_blank" } + end end if @order.ready_to_ship? links << { name: t(:ship_order), url: fire_admin_order_path(@order, :e => 'ship'), method: 'put', icon: 'icon-truck', confirm: t(:are_you_sure) } diff --git a/app/models/spree/address_decorator.rb b/app/models/spree/address_decorator.rb index 03fa4da0cd..db092f5eb2 100644 --- a/app/models/spree/address_decorator.rb +++ b/app/models/spree/address_decorator.rb @@ -20,6 +20,18 @@ Spree::Address.class_eval do filtered_address.compact.join(', ') end + def address_part1 + address_part1 = [address1, address2] + filtered_address = address_part1.select{ |field| !field.nil? && field != '' } + filtered_address.compact.join(', ') + end + + def address_part2 + address_part2= [city, zipcode, state.andand.name] + filtered_address = address_part2.select{ |field| !field.nil? && field != '' } + filtered_address.compact.join(', ') + end + private def touch_enterprise diff --git a/app/models/spree/adjustment_decorator.rb b/app/models/spree/adjustment_decorator.rb index c8529fc577..093f1c86fd 100644 --- a/app/models/spree/adjustment_decorator.rb +++ b/app/models/spree/adjustment_decorator.rb @@ -4,6 +4,7 @@ module Spree # So we don't need the option `dependent: :destroy` as long as # AdjustmentMetadata has no destroy logic itself. has_one :metadata, class_name: 'AdjustmentMetadata' + belongs_to :tax_rate, foreign_key: 'originator_id', conditions: "spree_adjustments.originator_type = 'Spree::TaxRate'" scope :enterprise_fee, where(originator_type: 'EnterpriseFee') scope :billable_period, where(source_type: 'BillablePeriod') diff --git a/app/models/spree/app_configuration_decorator.rb b/app/models/spree/app_configuration_decorator.rb index 570c7acc1e..2dfda8949c 100644 --- a/app/models/spree/app_configuration_decorator.rb +++ b/app/models/spree/app_configuration_decorator.rb @@ -4,6 +4,10 @@ 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. + # Terms of Service Preferences + preference :enterprises_require_tos, :boolean, default: false + preference :enterprise_tos_link, :string, default: "/Terms-of-service.pdf" + # Tax Preferences preference :products_require_tax_category, :boolean, default: false preference :shipping_tax_rate, :decimal, default: 0 @@ -28,4 +32,8 @@ Spree::AppConfiguration.class_eval do # External services preference :bugherd_api_key, :string, default: nil + + # Invoices & Receipts + preference :invoice_style2?, :boolean, default: false + preference :enable_receipt_printing?, :boolean, default: false end diff --git a/app/models/spree/line_item_decorator.rb b/app/models/spree/line_item_decorator.rb index 8a89d8fdef..31d263761f 100644 --- a/app/models/spree/line_item_decorator.rb +++ b/app/models/spree/line_item_decorator.rb @@ -56,6 +56,10 @@ Spree::LineItem.class_eval do adjustments.included_tax.sum(&:included_tax) end + def tax_rates + product.tax_category.andand.tax_rates || [] + end + def price_with_adjustments # EnterpriseFee#create_locked_adjustment applies adjustments on line items to their parent order, # so line_item.adjustments returns an empty array diff --git a/app/models/spree/order_decorator.rb b/app/models/spree/order_decorator.rb index c62f114177..8212840a8d 100644 --- a/app/models/spree/order_decorator.rb +++ b/app/models/spree/order_decorator.rb @@ -227,6 +227,26 @@ Spree::Order.class_eval do (adjustments + price_adjustments).sum &:included_tax end + def tax_adjustments + adjustments.with_tax + + line_items.includes(:adjustments).map {|li| li.adjustments.with_tax }.flatten + end + + def tax_adjustment_totals + tax_adjustments.each_with_object(Hash.new) do |adjustment, hash| + if adjustment.originator_type == "Spree::TaxRate" + tax_rate = adjustment.originator.amount + else + tax_rate = (adjustment.included_tax / (adjustment.amount - adjustment.included_tax)).round(2) + end + hash.update({tax_rate => adjustment.included_tax}) { |_tax_rate, amount1, amount2| amount1 + amount2 } + end + end + + def has_taxes_included + not line_items.with_tax.empty? + end + def account_invoice? distributor_id == Spree::Config.accounts_distributor_id end diff --git a/app/overrides/spree/admin/general_settings/edit/tos_settings.html.haml.deface b/app/overrides/spree/admin/general_settings/edit/tos_settings.html.haml.deface new file mode 100644 index 0000000000..9d573c3ac1 --- /dev/null +++ b/app/overrides/spree/admin/general_settings/edit/tos_settings.html.haml.deface @@ -0,0 +1,11 @@ +/ insert_after "fieldset.security" + +%fieldset.enterprise_toc.no-border-bottom + %legend{:align => "center"}= t(:enterprise_terms_of_service) + - [:enterprise_tos_link, :enterprises_require_tos].each do |pref| + - type = Spree::Config.preference_type(pref) + .field + = label_tag(pref, t(pref) + ': ') + tag(:br) if type != :boolean + = preference_field_tag(pref, Spree::Config[pref], :type => type) + = label_tag(pref, t(pref)) + tag(:br) if type == :boolean + diff --git a/app/overrides/spree/admin/orders/index/add_distributor_th.html.haml.deface b/app/overrides/spree/admin/orders/index/add_distributor_th.html.haml.deface index d5be7e956c..bba71ef434 100644 --- a/app/overrides/spree/admin/orders/index/add_distributor_th.html.haml.deface +++ b/app/overrides/spree/admin/orders/index/add_distributor_th.html.haml.deface @@ -1,4 +1,4 @@ / insert_top "[data-hook='admin_orders_index_headers']" %th - Distributor + = t(:products_distributor) diff --git a/app/overrides/spree/admin/payment_methods/index/add_distributor_th.html.haml.deface b/app/overrides/spree/admin/payment_methods/index/add_distributor_th.html.haml.deface index b14ca58392..6a46fe448c 100644 --- a/app/overrides/spree/admin/payment_methods/index/add_distributor_th.html.haml.deface +++ b/app/overrides/spree/admin/payment_methods/index/add_distributor_th.html.haml.deface @@ -1,4 +1,4 @@ / insert_after "[data-hook='admin_payment_methods_index_headers'] th:first-child" %th - Distributors + = t(:products_distributor) diff --git a/app/overrides/spree/admin/shared/_configuration_menu/add_accounts_and_billing.html.haml.deface b/app/overrides/spree/admin/shared/_configuration_menu/add_accounts_and_billing.html.haml.deface index 37754bb40e..eb6ab7c01b 100644 --- a/app/overrides/spree/admin/shared/_configuration_menu/add_accounts_and_billing.html.haml.deface +++ b/app/overrides/spree/admin/shared/_configuration_menu/add_accounts_and_billing.html.haml.deface @@ -1,4 +1,4 @@ // insert_bottom "[data-hook='admin_configurations_sidebar_menu']" %li - = link_to t(:accounts_and_billing), main_app.edit_admin_accounts_and_billing_settings_path + = link_to t('admin.accounts_and_billing_settings.edit.accounts_and_billing'), main_app.edit_admin_accounts_and_billing_settings_path diff --git a/app/overrides/spree/admin/shared/_configuration_menu/add_business_model_configuration.html.haml.deface b/app/overrides/spree/admin/shared/_configuration_menu/add_business_model_configuration.html.haml.deface index 7d5c311a7b..32d0edfda1 100644 --- a/app/overrides/spree/admin/shared/_configuration_menu/add_business_model_configuration.html.haml.deface +++ b/app/overrides/spree/admin/shared/_configuration_menu/add_business_model_configuration.html.haml.deface @@ -1,4 +1,4 @@ // insert_bottom "[data-hook='admin_configurations_sidebar_menu']" %li - = link_to 'Business Model', main_app.edit_admin_business_model_configuration_path + = link_to t('admin.business_model_configuration.edit.business_model_configuration'), main_app.edit_admin_business_model_configuration_path diff --git a/app/overrides/spree/admin/shared/_configuration_menu/add_caching.html.haml.deface b/app/overrides/spree/admin/shared/_configuration_menu/add_caching.html.haml.deface index 1eb416e72a..c320e072c0 100644 --- a/app/overrides/spree/admin/shared/_configuration_menu/add_caching.html.haml.deface +++ b/app/overrides/spree/admin/shared/_configuration_menu/add_caching.html.haml.deface @@ -1,4 +1,4 @@ / insert_bottom "[data-hook='admin_configurations_sidebar_menu']" %li - = link_to 'Caching', main_app.admin_cache_settings_path + = link_to t('admin.cache_settings.show.title'), main_app.admin_cache_settings_path diff --git a/app/overrides/spree/admin/shared/_configuration_menu/add_content.html.haml.deface b/app/overrides/spree/admin/shared/_configuration_menu/add_content.html.haml.deface index 0709cb9451..58ba1fc824 100644 --- a/app/overrides/spree/admin/shared/_configuration_menu/add_content.html.haml.deface +++ b/app/overrides/spree/admin/shared/_configuration_menu/add_content.html.haml.deface @@ -1,3 +1,3 @@ / insert_bottom "[data-hook='admin_configurations_sidebar_menu']" -%li= link_to 'Content', main_app.edit_admin_content_path +%li= link_to t('admin.contents.edit.title'), main_app.edit_admin_content_path diff --git a/app/overrides/spree/admin/shared/_configuration_menu/add_invoice_settings.html.haml.deface b/app/overrides/spree/admin/shared/_configuration_menu/add_invoice_settings.html.haml.deface new file mode 100644 index 0000000000..f65ed9eeea --- /dev/null +++ b/app/overrides/spree/admin/shared/_configuration_menu/add_invoice_settings.html.haml.deface @@ -0,0 +1,4 @@ +// insert_bottom "[data-hook='admin_configurations_sidebar_menu']" + +%li + = link_to t('admin.invoice_settings.edit.invoice_settings'), main_app.edit_admin_invoice_settings_path diff --git a/app/overrides/spree/admin/shipping_categories/index/add_temp_controlled_th.html.haml.deface b/app/overrides/spree/admin/shipping_categories/index/add_temp_controlled_th.html.haml.deface index 561e59bf91..0b41db13d5 100644 --- a/app/overrides/spree/admin/shipping_categories/index/add_temp_controlled_th.html.haml.deface +++ b/app/overrides/spree/admin/shipping_categories/index/add_temp_controlled_th.html.haml.deface @@ -1,4 +1,4 @@ / insert_after "[data-hook='categories_header'] th:first-child" %th - Temperature Controlled + = t(:temperature_controlled) diff --git a/app/overrides/spree/admin/shipping_methods/index/add_distributor_th.html.haml.deface b/app/overrides/spree/admin/shipping_methods/index/add_distributor_th.html.haml.deface index 620f02f965..618d758898 100644 --- a/app/overrides/spree/admin/shipping_methods/index/add_distributor_th.html.haml.deface +++ b/app/overrides/spree/admin/shipping_methods/index/add_distributor_th.html.haml.deface @@ -1,4 +1,4 @@ / insert_after "[data-hook='admin_shipping_methods_index_headers'] th:first-child" %th - Distributors + = t(:products_distributor) diff --git a/app/views/admin/accounts_and_billing_settings/_method_settings.html.haml b/app/views/admin/accounts_and_billing_settings/_method_settings.html.haml index 17037d47e9..32b1c0b9a5 100644 --- a/app/views/admin/accounts_and_billing_settings/_method_settings.html.haml +++ b/app/views/admin/accounts_and_billing_settings/_method_settings.html.haml @@ -1,10 +1,10 @@ .row .six.columns.alpha .field - = label :settings, :default_accounts_payment_method_id, t(:default_accounts_payment_method) + = label :settings, :default_accounts_payment_method_id, t('.default_accounts_payment_method') = collection_select(:settings, :default_accounts_payment_method_id, @payment_methods, :id, :name, { include_blank: true, selected: Spree::Config.default_accounts_payment_method_id}, { class: "select2 fullwidth" }) .six.columns.omega .field - = label :settings, :default_accounts_shipping_method_id, t(:default_accounts_shipping_method) + = label :settings, :default_accounts_shipping_method_id, t('.default_accounts_shipping_method') = collection_select(:settings, :default_accounts_shipping_method_id, @shipping_methods, :id, :name, { include_blank: true, selected: Spree::Config.default_accounts_shipping_method_id}, { class: "select2 fullwidth" }) diff --git a/app/views/admin/accounts_and_billing_settings/edit.html.haml b/app/views/admin/accounts_and_billing_settings/edit.html.haml index 83cfbbb76e..e17ceec637 100644 --- a/app/views/admin/accounts_and_billing_settings/edit.html.haml +++ b/app/views/admin/accounts_and_billing_settings/edit.html.haml @@ -1,7 +1,7 @@ = render :partial => 'spree/admin/shared/configuration_menu' - content_for :page_title do - = t(:accounts_and_billing) + = t('.accounts_and_billing') = render 'spree/shared/error_messages', target: @settings @@ -9,12 +9,12 @@ %fieldset.no-border-bottom %legend - = t(:admin_settings) + = t('.admin_settings') = form_for @settings, as: :settings, url: main_app.admin_accounts_and_billing_settings_path, :method => :put do |f| .row{ ng: { app: 'admin.accounts_and_billing_settings' } } .twelve.columns.alpha.omega .field - = f.label :accounts_distributor_id, t(:accounts_administration_distributor) + = f.label :accounts_distributor_id, t('.accounts_administration_distributor') = f.collection_select(:accounts_distributor_id, @distributors, :id, :name, { include_blank: true }, { class: "select2 fullwidth", 'watch-value-as' => "enterprise_id"}) = f.hidden_field :default_accounts_payment_method_id, value: '' @@ -25,18 +25,16 @@ .six.columns.alpha %fieldset.no-border-bottom %legend - =t :update_invoice + = t('.update_invoice') = f.check_box :auto_update_invoices - = f.label :auto_update_invoices, - t(:auto_update_invoices) + = f.label :auto_update_invoices, t('.auto_update_invoices') .six.columns.omega %fieldset.no-border-bottom %legend - =t :finalise_invoice + = t('.finalise_invoice') = f.check_box :auto_finalize_invoices - = f.label :auto_finalize_invoices, - t(:auto_finalise_invoices) + = f.label :auto_finalize_invoices, t('.auto_finalise_invoices') .row .twelve.columns.alpha.omega.form-buttons{"data-hook" => "buttons"} @@ -44,36 +42,35 @@ %fieldset.no-border-bottom %legend - =t :manually_run_task + =t('.manually_run_task') .row .six.columns.alpha.step.text-center .form-buttons{"data-hook" => "buttons"} - =link_to_with_icon "icon-undo", - t(:update_user_invoices) , - main_app.start_job_admin_accounts_and_billing_settings_path(job: { name: "update_account_invoices" }), - class: "button fullwidth" + = link_to_with_icon "icon-undo", t('.update_user_invoices'), + main_app.start_job_admin_accounts_and_billing_settings_path(job: { name: "update_account_invoices" }), + class: "button fullwidth" %br - if @update_account_invoices_job %p.text-center - if @update_account_invoices_job.run_at < Time.zone.now - =t :in_progress + = t(:in_progress) %br - =t :started_at + = t(:started_at) - else %strong - =t :queued + = t(:queued) %br - =t :Scheduled_for + = t(:scheduled_for) = @update_account_invoices_job.run_at - else %p.explanation - =t :update_user_invoice_explained + = t('.update_user_invoice_explained') .six.columns.omega.step.text-center .form-buttons{"data-hook" => "buttons"} - =link_to_with_icon "icon-ok-sign", t(:finalise_user_invoices ), + =link_to_with_icon "icon-ok-sign", t('.finalise_user_invoices'), main_app.start_job_admin_accounts_and_billing_settings_path(job: { name: "finalize_account_invoices" }), class: "button fullwidth" @@ -83,15 +80,15 @@ %p.text-center - if @finalize_account_invoices_job.run_at < Time.zone.now %strong - =t :in_progress + = t(:in_progress) %br - =t :started_at + = t(:started_at) - else %strong - =t :queued + = t(:queued) %br - =t :scheduled_for + = t(:scheduled_for) = @finalize_account_invoices_job.run_at - else %p.explanation - =t :finalise_user_invoice_explained + = t('.finalise_user_invoice_explained') diff --git a/app/views/admin/business_model_configuration/edit.html.haml b/app/views/admin/business_model_configuration/edit.html.haml index 04ee47e45d..29139d78bf 100644 --- a/app/views/admin/business_model_configuration/edit.html.haml +++ b/app/views/admin/business_model_configuration/edit.html.haml @@ -4,57 +4,58 @@ = "ng-app='admin.businessModelConfiguration'" - content_for :page_title do - %h1.page-title= t(:business_model_configuration) - %a{ 'ofn-with-tip' => "Configure the rate at which shops will be charged each month for use of the Open Food Network." } What's this? + %h1.page-title= t('.business_model_configuration') + %a{ 'ofn-with-tip' => t('.business_model_configuration_tip') } + = t('admin.whats_this') = render 'spree/shared/error_messages', target: @settings .row{ ng: { controller: "BusinessModelConfigCtrl" } } .five.columns.omega %fieldset.no-border-bottom - %legend=t(:bill_calculation_settings) + %legend=t('.bill_calculation_settings') %p - Adjust the amount that enterprises will be billed each month for use of the OFN. + = t('.bill_calculation_settings_tip') %br = form_for @settings, as: :settings, url: main_app.admin_business_model_configuration_path, :method => :put do |f| .row .three.columns.alpha - = f.label :shop_trial_length_days, t(:shop_trial_length) - %span.icon-question-sign{'ofn-with-tip' => "The length of time (in days) that enterprises who are set up as shops can run as a trial period."} + = f.label :shop_trial_length_days, t('.shop_trial_length') + %span.icon-question-sign{'ofn-with-tip' => t('.shop_trial_length_tip')} .two.columns.omega = f.number_field :shop_trial_length_days, min: 0.0, step: 1.0, class: "fullwidth" .row .three.columns.alpha - = f.label :account_invoices_monthly_fixed, t(:fixed_monthly_charge) - %span.icon-question-sign{'ofn-with-tip' => "A fixed monthly charge for all enterprises who are set up as a shop and have exceeded the minimum billable turnover (if set)."} + = f.label :account_invoices_monthly_fixed, t('.fixed_monthly_charge') + %span.icon-question-sign{'ofn-with-tip' => t('.fixed_monthly_charge_tip')} .two.columns.omega .input-symbol.before %span= Spree::Money.currency_symbol = f.number_field :account_invoices_monthly_fixed, min: 0.0, class: "fullwidth", 'watch-value-as' => 'fixed' .row .three.columns.alpha - = f.label :account_invoices_monthly_rate, t(:percentage_of_turnover) - %span.icon-question-sign{'ofn-with-tip' => "When greater than zero, this rate (0.0 - 1.0) will be applied to the total turnover of each shop and added to any fixed charges (to the left) to calculate the monthly bill."} + = f.label :account_invoices_monthly_rate, t('.percentage_of_turnover') + %span.icon-question-sign{'ofn-with-tip' => t('.percentage_of_turnover_tip')} .two.columns.omega = f.number_field :account_invoices_monthly_rate, min: 0.0, max: 1.0, step: 0.01, class: "fullwidth", 'watch-value-as' => 'rate' .row .three.columns.alpha - = f.label :account_invoices_monthly_cap, t(:monthly_cap_excl_tax) - %span.icon-question-sign{'ofn-with-tip' => "When greater than zero, this value will be used as a cap on the amount that shops will be charged each month."} + = f.label :account_invoices_monthly_cap, t('.monthly_cap_excl_tax') + %span.icon-question-sign{'ofn-with-tip' => t('.monthly_cap_excl_tax_tip')} .two.columns.omega .input-symbol.before %span= Spree::Money.currency_symbol = f.number_field :account_invoices_monthly_cap, min: 0.0, class: "fullwidth", 'watch-value-as' => 'cap' .row .three.columns.alpha - = f.label :account_invoices_tax_rate, t(:tax_rate) - %span.icon-question-sign{'ofn-with-tip' => "Tax rate that applies to the the monthly bill that enterprises are charged for using the system."} + = f.label :account_invoices_tax_rate, t('.tax_rate') + %span.icon-question-sign{'ofn-with-tip' => t('.tax_rate_tip')} .two.columns.omega = f.number_field :account_invoices_tax_rate, min: 0.0, max: 1.0, step: 0.01, class: "fullwidth", 'watch-value-as' => 'taxRate' .row .three.columns.alpha - = f.label :minimum_billable_turnover, t(:minimum_monthly_billable_turnover) - %span.icon-question-sign{'ofn-with-tip' => "Minimum monthly turnover before a shopfront will be charged for using OFN. Enterprises turning over less than this amount in a month will not be charged, either as a percentage or fixed rate."} + = f.label :minimum_billable_turnover, t('.minimum_monthly_billable_turnover') + %span.icon-question-sign{'ofn-with-tip' => t('.minimum_monthly_billable_turnover_tip')} .two.columns.omega .input-symbol.before %span= Spree::Money.currency_symbol @@ -69,35 +70,35 @@ .five.columns.alpha %fieldset.no-border-bottom - %legend=t(:example_bill_calculator) + %legend= t('.example_bill_calculator') %p - Alter the example turnover to visualise the effect of the settings to the left. + = t('.example_bill_calculator_legend') %br .row .three.columns.alpha - = label_tag :turnover, t(:example_monthly_turnover) - %span.icon-question-sign{'ofn-with-tip' => "An example monthly turnover for an enterprise which will be used to generate calculate an example monthly bill below."} + = label_tag :turnover, t('.example_monthly_turnover') + %span.icon-question-sign{'ofn-with-tip' => t('.example_monthly_turnover_tip')} .two.columns.omega .input-symbol.before %span= Spree::Money.currency_symbol %input.fullwidth{ id: 'turnover', type: "number", ng: { model: 'turnover' } } .row .three.columns.alpha - = label_tag :cap_reached, t(:cap_reached?) - %span.icon-question-sign{'ofn-with-tip' => "Whether the cap (specified to the left) has been reached, given the settings and the turnover provided."} + = label_tag :cap_reached, t('.cap_reached?') + %span.icon-question-sign{'ofn-with-tip' => t('.cap_reached?_tip')} .two.columns.omega %input.fullwidth{ id: 'cap_reached', type: "text", readonly: true, ng: { value: 'capReached()' } } .row .three.columns.alpha - = label_tag :included_tax, t(:included_tax) - %span.icon-question-sign{'ofn-with-tip' => "The total tax included in the example monthly bill, given the settings and the turnover provided."} + = label_tag :included_tax, t('.included_tax') + %span.icon-question-sign{'ofn-with-tip' => t('.included_tax_tip')} .two.columns.omega %span= Spree::Money.currency_symbol %input.fullwidth{ id: 'included_tax', type: "text", readonly: true, ng: { value: 'includedTax()' } } .row .three.columns.alpha - = label_tag :total_incl_tax, t(:total_monthly_bill_incl_tax) - %span.icon-question-sign{'ofn-with-tip' => "The example total monthly bill with tax included, given the settings and the turnover provided."} + = label_tag :total_incl_tax, t('.total_monthly_bill_incl_tax') + %span.icon-question-sign{'ofn-with-tip' => t('.total_monthly_bill_incl_tax_tip')} .two.columns.omega %span= Spree::Money.currency_symbol %input.fullwidth{ id: 'total_incl_tax', type: "text", readonly: true, ng: { value: 'total()' } } diff --git a/app/views/admin/enterprises/_enterprise_user_index.html.haml b/app/views/admin/enterprises/_enterprise_user_index.html.haml index 4b777e127b..b4bc32d2ad 100644 --- a/app/views/admin/enterprises/_enterprise_user_index.html.haml +++ b/app/views/admin/enterprises/_enterprise_user_index.html.haml @@ -10,10 +10,9 @@ .row{ 'ng-if' => '!loaded' } .sixteen.columns.alpha#loading %img.spinner{ src: "/assets/spinning-circles.svg" } - %h1 LOADING ENTERPRISES + %h1= t('.loading_enterprises') .row{ :class => "sixteen columns alpha", 'ng-show' => 'loaded && filteredEnterprises.length == 0'} - %h1#no_results No enterprises found. - + %h1#no_results= t('.no_enterprises_found') .row{ ng: { show: "loaded && filteredEnterprises.length > 0" } } %table.index#enterprises diff --git a/app/views/admin/enterprises/form/_about_us.html.haml b/app/views/admin/enterprises/form/_about_us.html.haml index 32550b711b..fdc9827e4f 100644 --- a/app/views/admin/enterprises/form/_about_us.html.haml +++ b/app/views/admin/enterprises/form/_about_us.html.haml @@ -14,4 +14,4 @@ -# ['html', 'insertImage', 'insertLink', 'insertVideo'] %text-angular{'ng-model' => 'Enterprise.long_description', 'id' => 'enterprise_long_description', 'name' => 'enterprise[long_description]', 'class' => 'text-angular', 'ta-toolbar' => "[['h1','h2','h3','h4','p'],['bold','italics','underline','clear'],['insertLink']]", - 'placeholder' => t('.desc_long_placeholder')} \ No newline at end of file + 'placeholder' => t('.desc_long_placeholder')} diff --git a/app/views/admin/enterprises/form/_business_details.html.haml b/app/views/admin/enterprises/form/_business_details.html.haml index 4015e51282..e14254ef5d 100644 --- a/app/views/admin/enterprises/form/_business_details.html.haml +++ b/app/views/admin/enterprises/form/_business_details.html.haml @@ -21,3 +21,13 @@ = f.radio_button :charges_sales_tax, false = f.label :charges_sales_tax, t(:say_no), value: 'false' +.row + .alpha.three.columns + = f.label :display_invoice_logo, 'Display logo in invoices' + .omega.eight.columns + = f.check_box :display_invoice_logo +.row + .alpha.three.columns + = f.label :invoice_text, 'Add customized text at the end of invoices' + .omega.eight.columns + = f.text_area :invoice_text, style: "width: 100%; height: 100px;" diff --git a/app/views/admin/invoice_settings/edit.html.haml b/app/views/admin/invoice_settings/edit.html.haml new file mode 100644 index 0000000000..e134356927 --- /dev/null +++ b/app/views/admin/invoice_settings/edit.html.haml @@ -0,0 +1,19 @@ += render :partial => 'spree/admin/shared/configuration_menu' + +- content_for :page_title do + = t('.title') + += form_tag main_app.admin_invoice_settings_path, :method => :put do + + .field.align-center + = hidden_field_tag 'preferences[invoice_style2?]', '0' + = check_box_tag 'preferences[invoice_style2?]', '1', Spree::Config[:invoice_style2?] + = label_tag nil, t('.invoice_style2?') + + .field.align-center + = hidden_field_tag 'preferences[enable_receipt_printing?]', '0' + = check_box_tag 'preferences[enable_receipt_printing?]', '1', Spree::Config[:enable_receipt_printing?] + = label_tag nil, t('.enable_receipt_printing?') + + .form-buttons{"data-hook" => "buttons"} + = button t(:update), 'icon-refresh' diff --git a/app/views/checkout/_shipping_ship_address.html.haml b/app/views/checkout/_shipping_ship_address.html.haml index fa87eef2ff..7b4db0d54c 100644 --- a/app/views/checkout/_shipping_ship_address.html.haml +++ b/app/views/checkout/_shipping_ship_address.html.haml @@ -3,26 +3,26 @@ %div.visible{"ng-if" => "!Checkout.ship_address_same_as_billing"} .row .small-6.columns - = validated_input "First Name", "order.ship_address.firstname", "ofn-focus" => "accordion['shipping']" + = validated_input t(:first_name), "order.ship_address.firstname", "ofn-focus" => "accordion['shipping']" .small-6.columns - = validated_input "Last Name", "order.ship_address.lastname" + = validated_input t(:last_name), "order.ship_address.lastname" .row .small-12.columns - = validated_input "Address", "order.ship_address.address1" + = validated_input t(:address), "order.ship_address.address1" .row .small-12.columns - = validated_input "Address (contd.)", "order.ship_address.address2", required: false + = validated_input t(:address2), "order.ship_address.address2", required: false .row .small-6.columns - = validated_input "City", "order.ship_address.city" + = validated_input t(:city), "order.ship_address.city" .small-6.columns - = validated_select "State", "order.ship_address.state_id", checkout_state_options(:shipping) + = validated_select t(:state), "order.ship_address.state_id", checkout_state_options(:shipping) .row .small-6.columns - = validated_input "Postcode", "order.ship_address.zipcode" + = validated_input t(:postcode), "order.ship_address.zipcode" .small-6.columns.right - = validated_select "Country", "order.ship_address.country_id", checkout_country_options + = validated_select t(:country), "order.ship_address.country_id", checkout_country_options .row .small-6.columns - = validated_input "Phone", "order.ship_address.phone" + = validated_input t(:phone), "order.ship_address.phone" diff --git a/app/views/registration/_modal.html.haml b/app/views/registration/_modal.html.haml new file mode 100644 index 0000000000..5fa1da9296 --- /dev/null +++ b/app/views/registration/_modal.html.haml @@ -0,0 +1,11 @@ +%script{ type: "text/ng-template", id: "registration.html" } + %div#registration-modal{"ng-controller" => "RegistrationCtrl"} + %div{ ng: { show: "currentStep() == 'introduction'" } } + %ng-include{ src: "'registration/introduction.html'" } + %div{ ng: { repeat: 'step in steps', show: "currentStep() == step" } } + %ng-include{ src: "'registration/'+ step + '.html'" } + %div{ ng: { show: "currentStep() == 'finished'" } } + %ng-include{ src: "'registration/finished.html'" } + + %a.close-reveal-modal{"ng-click" => "$close()"} + %i.ofn-i_009-close diff --git a/app/views/registration/index.html.haml b/app/views/registration/index.html.haml index fdeef18534..4f23ac8700 100644 --- a/app/views/registration/index.html.haml +++ b/app/views/registration/index.html.haml @@ -5,4 +5,10 @@ = inject_available_countries = inject_enterprise_attributes +- steps = %w{about contact details finished images introduction} +- steps += %w{limit_reached logo promo social steps type} +- steps.each do |step| + = render partial: "registration/steps/#{step}" += render "modal" + %div{ "ng-controller" => "RegistrationCtrl" } diff --git a/app/views/registration/steps/_about.html.haml b/app/views/registration/steps/_about.html.haml new file mode 100644 index 0000000000..529fdebea3 --- /dev/null +++ b/app/views/registration/steps/_about.html.haml @@ -0,0 +1,57 @@ +%script{ type: "text/ng-template", id: "registration/about.html" } + .container#registration-about + %ng-include{ src: "'registration/steps.html'" } + .row + .small-12.columns + %header + %h2 {{'enterprise_about_headline' | t}} + %h5 + {{'enterprise_about_message' | t}} + %span{ ng: { class: "{brick: !enterprise.is_primary_producer, turquoise: enterprise.is_primary_producer}" } } + {{ enterprise.name }} + + %form{ name: 'about', novalidate: true, ng: { controller: "RegistrationFormCtrl", submit: "update('images',about)" } } + .row + .small-12.columns + .alert-box.info{ "ofn-inline-alert" => true, ng: { show: "visible" } } + %h6{ "ng-bind" => "'enterprise_success' | t:{enterprise: enterprise.name}" } + %span {{'enterprise_registration_exit_message' | t}} + %a.close{ ng: { click: "close()" } } × + + .small-12.large-8.columns + .row + .small-12.columns + .field + %label{ for: 'enterprise_description' } {{'enterprise_description' | t}}: + %input.chunky{ id: 'enterprise_description', placeholder: "{{'enterprise_description_placeholder' | t}}", ng: { model: 'enterprise.description' } } + .row + .small-12.columns + .field + %label{ for: 'enterprise_long_desc' } {{'enterprise_long_desc' | t}}: + %textarea.chunky{ id: 'enterprise_long_desc', rows: 6, placeholder: "{{'enterprise_long_desc_placeholder' | t}}", ng: { model: 'enterprise.long_description' } } + %small{ "ng-bind" => "'enterprise_long_desc_length' | t:{num: enterprise.long_description.length}" } + .small-12.large-4.columns + .row + .small-12.columns + .field + %label{ for: 'enterprise_abn' } {{'enterprise_abn' | t}}: + %input.chunky{ id: 'enterprise_abn', placeholder: "{{'enterprise_abn_placeholder' | t}}", ng: { model: 'enterprise.abn' } } + .row + .small-12.columns + .field + %label{ for: 'enterprise_acn' } {{'enterprise_acn' | t}}: + %input.chunky{ id: 'enterprise_acn', placeholder: "{{'enterprise_acn_placeholder' | t}}", ng: { model: 'enterprise.acn' } } + .row + .small-12.columns + .field + %label{ for: 'enterprise_charges_sales_tax' }= t(:charges_sales_tax) + %input{ id: 'enterprise_charges_sales_tax_true', type: 'radio', name: 'charges_sales_tax', value: 'true', required: true, ng: { model: 'enterprise.charges_sales_tax' } } + %label{ for: 'enterprise_charges_sales_tax_true' } {{'say_yes' | t}} + %input{ id: 'enterprise_charges_sales_tax_false', type: 'radio', name: 'charges_sales_tax', value: 'false', required: true, ng: { model: 'enterprise.charges_sales_tax' } } + %label{ for: 'enterprise_charges_sales_tax_false' } {{'say_no' | t}} + %span.error.small-12.columns{ ng: { show: "about.charges_sales_tax.$error.required && submitted" } } + {{'enterprise_tax_required' | t}} + + .row.buttons.pad-top + .small-12.columns + %input.button.primary.right{ type: "submit", value: "{{'continue' | t}}" } diff --git a/app/views/registration/steps/_contact.html.haml b/app/views/registration/steps/_contact.html.haml new file mode 100644 index 0000000000..3b7d43ae72 --- /dev/null +++ b/app/views/registration/steps/_contact.html.haml @@ -0,0 +1,32 @@ +%script{ type: "text/ng-template", id: "registration/contact.html" } + .container#registration-contact + %ng-include{ src: "'registration/steps.html'" } + .row + .small-12.columns + %header + %h2 {{'registration_greeting' | t}} + %h5{ "ng-bind" => "'who_is_managing_enterprise' | t:{enterprise: enterprise.name}" } + + %form{ name: 'contact', novalidate: true, ng: { controller: "RegistrationFormCtrl", submit: "selectIfValid('type',contact)" } } + .row.content + .small-12.medium-12.large-7.columns + .row + .small-12.columns.field + %label{ for: 'enterprise_contact' } {{'enterprise_contact' | t}}: + %input.chunky.small-12.columns{ id: 'enterprise_contact', name: 'contact', required: true, placeholder: "Contact Name", ng: { model: 'enterprise.contact' } } + %span.error.small-12.columns{ ng: { show: "contact.contact.$error.required && submitted" } } + {{'enterprise_contact_required' | t}} + .row + .small-12.columns.field + %label{ for: 'enterprise_email_address' } {{'enterprise_email_address' | t}}: + %input.chunky.small-12.columns{ id: 'enterprise_email_address', name: 'email_address', type: 'email', placeholder: "eg. charlie@thefarm.com", ng: { model: 'enterprise.email_address' } } + .row + .small-12.columns.field + %label{ for: 'enterprise_phone' } {{'enterprise_phone' | t}}: + %input.chunky.small-12.columns{ id: 'enterprise_phone', name: 'phone', placeholder: "eg. (03) 1234 5678", ng: { model: 'enterprise.phone' } } + .small-12.medium-12.large-5.hide-for-small-only + + .row.buttons + .small-12.columns + %input.button.secondary{ type: "button", value: "{{'back' | t}}", ng: { click: "select('details')" } } + %input.button.primary.right{ type: "submit", value: "{{'continue' | t}}" } diff --git a/app/views/registration/steps/_details.html.haml b/app/views/registration/steps/_details.html.haml new file mode 100644 index 0000000000..dd3ee65085 --- /dev/null +++ b/app/views/registration/steps/_details.html.haml @@ -0,0 +1,65 @@ +%script{ type: "text/ng-template", id: "registration/details.html" } + .container#registration-details + %ng-include{ src: "'registration/steps.html'" } + .row + .small-12.columns + %header + %h2 {{'registration_detail_headline' | t}} + %h5{ ng: { if: "::enterprise.type != 'own'" } } {{'registration_detail_enterprise' | t}} + %h5{ ng: { if: "::enterprise.type == 'own'" } } {{'registration_detail_producer' | t}} + + %form{ name: 'details', novalidate: true, ng: { controller: "RegistrationFormCtrl", submit: "selectIfValid('contact',details)" } } + + .row + .small-12.medium-9.large-12.columns.end + .field + %label{ for: 'enterprise_name', ng: { if: "::enterprise.type != 'own'" } } {{'registration_detail_name_enterprise' | t}} + %label{ for: 'enterprise_name', ng: { if: "::enterprise.type == 'own'" } } {{'registration_detail_name_producer' | t}} + %input.chunky{ id: 'enterprise_name', name: 'name', placeholder: "{{'registration_detail_name_placeholder' | t}}", required: true, ng: { model: 'enterprise.name' } } + %span.error{ ng: { show: "details.name.$error.required && submitted" } } + {{'registration_detail_name_error' | t}} + + .row + .small-12.medium-9.large-6.columns + .field + %label{ for: 'enterprise_address' } {{'registration_detail_address1' | t}} + %input.chunky{ id: 'enterprise_address', name: 'address1', required: true, placeholder: "{{'registration_detail_address1_placeholder' | t}}", required: true, ng: { model: 'enterprise.address.address1' } } + %span.error{ ng: { show: "details.address1.$error.required && submitted" } } + {{'registration_detail_address1_error' | t}} + .field + %label{ for: 'enterprise_address2' } {{'registration_detail_address2' | t}} + %input.chunky{ id: 'enterprise_address2', name: 'address2', required: false, placeholder: "", required: false, ng: { model: 'enterprise.address.address2' } } + + .small-12.medium-9.large-6.columns.end + .row + .small-12.medium-8.large-8.columns + .field + %label{ for: 'enterprise_city' } {{'registration_detail_suburb' | t}} + %input.chunky{ id: 'enterprise_city', name: 'city', required: true, placeholder: "{{'registration_detail_suburb_placeholder' | t}}", ng: { model: 'enterprise.address.city' } } + %span.error{ ng: { show: "details.city.$error.required && submitted" } } + {{'registration_detail_suburb_error' | t}} + .small-12.medium-4.large-4.columns + .field + %label{ for: 'enterprise_zipcode' } {{'registration_detail_postcode' | t}} + %input.chunky{ id: 'enterprise_zipcode', name: 'zipcode', required: true, placeholder: "{{'registration_detail_postcode_placeholder' | t}}", ng: { model: 'enterprise.address.zipcode' } } + %span.error{ ng: { show: "details.zipcode.$error.required && submitted" } } + {{'registration_detail_postcode_error' | t}} + .row + .small-12.medium-4.large-4.columns + .field + %label{ for: 'enterprise_state' } {{'registration_detail_state' | t}} + %select.chunky{ id: 'enterprise_state', name: 'state', ng: { model: 'enterprise.address.state_id', options: 's.id as s.abbr for s in enterprise.country.states', show: 'countryHasStates()', required: 'countryHasStates()' } } + %span.error{ ng: { show: "details.state.$error.required && submitted" } } + {{'registration_detail_state_error' | t}} + .small-12.medium-8.large-8.columns + .field + %label{ for: 'enterprise_country' } {{'registration_detail_country' | t}} + %select.chunky{ id: 'enterprise_country', name: 'country', required: true, ng: { model: 'enterprise.country', options: 'c as c.name for c in countries' } } + %span.error{ ng: { show: "details.country.$error.required && submitted" } } + {{'registration_detail_country_error' | t}} + + + .row.buttons + .small-12.columns + %hr + %input.button.primary.right{ type: "submit", value: "{{'continue' | t}}" } diff --git a/app/views/registration/steps/_finished.html.haml b/app/views/registration/steps/_finished.html.haml new file mode 100644 index 0000000000..bae5397a29 --- /dev/null +++ b/app/views/registration/steps/_finished.html.haml @@ -0,0 +1,16 @@ +%script{ type: "text/ng-template", id: "registration/finished.html" } + .container#registration-finished + .row + .small-12.columns.pad-top + %header + %h2 {{'registration_finished_headline' | t}} + .panel.callout + %p{ "ng-bind" => "'registration_finished_thanks' | t:{enterprise: enterprise.name}" } + %p {{'registration_finished_login' | t}} + .row + .small-12.columns.text-center + %h4{ "ng-bind" => "'registration_finished_activate' | t:{enterprise: enterprise.name}" } + + %p{ "ng-bind-html" => "'registration_finished_activate_instruction_html' | t:{email: enterprise.email}"} + + %a.button.primary{ type: "button", href: "/" } {{'registration_finished_action' | t}} > diff --git a/app/views/registration/steps/_images.html.haml b/app/views/registration/steps/_images.html.haml new file mode 100644 index 0000000000..f888bd8165 --- /dev/null +++ b/app/views/registration/steps/_images.html.haml @@ -0,0 +1,23 @@ +%script{ type: "text/ng-template", id: "registration/images.html" } + .container#registration-images{ 'nv-file-drop' => true, uploader: "imageUploader", options:"{ alias: imageStep }", ng: { controller: "EnterpriseImageCtrl" } } + %ng-include{ src: "'registration/steps.html'" } + .row + .small-12.columns + %header + %h2 {{'registration_images_headline' | t}} + %h5 {{'registration_images_description' | t}} + + %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/'+ image_step + '.html'" } + + .row.buttons.pad-top{ ng: { if: "imageStep == 'logo'" } } + .small-12.columns + %input.button.secondary{ type: "button", value: "Back", ng: { click: "select('about')" } } + + %input.button.primary.right{ type: "button", value: "Continue", ng: { click: "imageSelect('promo')" } } + + .row.buttons.pad-top{ ng: { if: "imageStep == 'promo'" } } + .small-12.columns + %input.button.secondary{ type: "button", value: "{{'back' | t}}", ng: { click: "imageSelect('logo')" } } + %input.button.primary.right{ type: "submit", value: "{{'continue' | t}}" } diff --git a/app/views/registration/steps/_introduction.html.haml b/app/views/registration/steps/_introduction.html.haml new file mode 100644 index 0000000000..c663886a03 --- /dev/null +++ b/app/views/registration/steps/_introduction.html.haml @@ -0,0 +1,46 @@ +%script{ type: "text/ng-template", id: "registration/introduction.html" } + .row + .small-12.columns + %header + %h2 {{'registration_greeting' | t}} + %h4 + %small + %i.ofn-i_040-hub + {{'registration_intro' | t}} + + .row{ 'data-equalizer' => true } + .small-12.medium-12.large-6.columns.pad-top{ 'data-equalizer-watch' => true } + %h5 {{'registration_checklist' | t}}: + %ul.check-list + %li + {{'registration_time' | t}} + %li + {{'registration_enterprise_address' | t}} + %li + {{'registration_contact_details' | t}} + %li + {{'registration_logo' | t}} + %li + {{'registration_promo_image' | t}} + %li + {{'registration_about_us' | t}} + + .small-9.medium-8.large-5.columns.pad-top.end{ 'data-equalizer-watch' => true} + %h5 + {{'registration_outcome_headline' | t}} + %p{ "ng-bind-html" => "t('registration_outcome1_html')" } + %p {{'registration_outcome2' | t}} + %p {{'registration_outcome3' | t}} + + .row{'ng-init' => "tos_required=#{Spree::Config.enterprises_require_tos}" } + %hr + .small-12.columns{'ng-hide' => '!tos_required' } + %p.tos-message + #{t(:enterprise_tos_message)} + %a{href: "#{Spree::Config.enterprise_tos_link}", target: "_blank" } #{t(:enterprise_tos_link_text)} + %p.tos-checkbox + %input{ type: 'checkbox', name: 'accept_terms', id: 'accept_terms', ng: { model: "tos_accepted" } } + %label{for: "accept_terms"} #{t(:enterprise_tos_agree)} + + .small-12.columns + %input.button.primary.left{ type: "button", value: "{{'registration_action' | t}}", ng: { click: "select('details')", disabled: "tos_required && !tos_accepted", model: "tos_accepted"} } diff --git a/app/views/registration/steps/_limit_reached.html.haml b/app/views/registration/steps/_limit_reached.html.haml new file mode 100644 index 0000000000..44f3b53f22 --- /dev/null +++ b/app/views/registration/steps/_limit_reached.html.haml @@ -0,0 +1,17 @@ +%script{ type: "text/ng-template", id: "registration/limit_reached.html" } + .row + .small-12.columns + %header + %h2 {{'limit_reached_headline' | t}} + %h4 {{'limit_reached_message' | t}} + .row + .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 + {{'limit_reached_text' | t}} + %strong Open Food Network. + .row + .small-12.columns + %hr + %input.button.primary{ type: "button", value: "{{'limit_reached_action' | t}}", ng: { click: "close()" } } diff --git a/app/views/registration/steps/_logo.html.haml b/app/views/registration/steps/_logo.html.haml new file mode 100644 index 0000000000..3d1effdf93 --- /dev/null +++ b/app/views/registration/steps/_logo.html.haml @@ -0,0 +1,46 @@ +%script{ type: "text/ng-template", id: "registration/logo.html" } + .small-12.medium-12.large-6.columns + .row + .small-12.columns.center + .row + .small-12.columns.center + %h4 + {{'select_logo' | t}} + .row + .small-12.columns.center + %span.small + {{'logo_tip' | t}} + .row.pad-top + .small-12.columns + .image-select.small-12.columns + %label.small-12.columns.button{ for: 'image-select' } {{'logo_label' | t}} + %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 + {{'action_or' | t}} + .row.show-for-large-up + .large-12.columns + #image-over{ 'nv-file-over' => true, uploader: "imageUploader" } + {{'logo_drag' | t}} + .small-12.medium-12.large-6.columns + .row + .small-12.columns.center + .row + .small-12.columns.center + %h4 + {{'review_logo' | t}} + .row + .small-12.columns.center + %span.small + {{'review_logo_tip' | t}} + .row.pad-top + .small-12.columns.center + #image-placeholder.logo + %img{ ng: { show: "imageSrc() && !imageUploader.isUploading", src: '{{ imageSrc() }}' } } + .message{ ng: { hide: "imageSrc() || imageUploader.isUploading" } } + {{'logo_placeholder' | t}} + .loading{ ng: { hide: "!imageUploader.isUploading" } } + %img.spinner{ src: "/assets/spinning-circles.svg" } + %br/ + {{'uploading' | t}} diff --git a/app/views/registration/steps/_promo.html.haml b/app/views/registration/steps/_promo.html.haml new file mode 100644 index 0000000000..0b224e1f64 --- /dev/null +++ b/app/views/registration/steps/_promo.html.haml @@ -0,0 +1,44 @@ +%script{ type: "text/ng-template", id: "registration/promo.html" } + .small-12.medium-12.large-12.columns + .row + .small-12.columns.center + %h4 + {{'select_promo_image' | t}} + .row + .small-12.medium-12.large-5.columns.center + .row + .small-12.columns.center + %span.small + {{'promo_image_tip' | t}} + .row.pad-top + .small-12.columns + .image-select.small-12.columns + %label.small-12.columns.button{ for: 'image-select' } {{'promo_image_label' | t}} + %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 + {{'action_or' | t}} + .large-5.columns + #image-over{ 'nv-file-over' => true, uploader: "imageUploader" } + {{'promo_image_drag' | t}} + .small-12.medium-12.large-12.columns.pad-top + .row + .small-12.columns.center + %h4 + {{'review_promo_image' | t}} + .row + .small-12.columns.center + .row + .small-12.columns.center + %span.small + {{'review_promo_image_tip' | t}} + .row.pad-top + .small-12.columns.center + #image-placeholder.promo + %img{ ng: { show: "imageSrc() && !imageUploader.isUploading", src: '{{ imageSrc() }}' } } + .message{ ng: { hide: "imageSrc() || imageUploader.isUploading" } } + {{'promo_image_placeholder' | t}} + .loading{ ng: { hide: "!imageUploader.isUploading" } } + %img.spinner{ src: "/assets/spinning-circles.svg" } + %br/ + {{'uploading' | t}} diff --git a/app/views/registration/steps/_social.html.haml b/app/views/registration/steps/_social.html.haml new file mode 100644 index 0000000000..edbdd94dd9 --- /dev/null +++ b/app/views/registration/steps/_social.html.haml @@ -0,0 +1,44 @@ +%script{ type: "text/ng-template", id: "registration/social.html" } + .container#registration-social + %ng-include{ src: "'registration/steps.html'" } + + .row + .small-12.columns + %header + %h2 {{'enterprise_final_step' | t}} + %h5{ "ng-bind" => "'enterprise_social_text' | t:{enterprise: enterprise.name}" } + + %form{ name: 'social', novalidate: true, ng: { controller: "RegistrationFormCtrl", submit: "update('finished',social)" } } + .row.content + .small-12.large-7.columns + .row + .small-12.columns + .field + %label{ for: 'enterprise_website' } {{'website' | t}}: + %input.chunky{ id: 'enterprise_website', placeholder: "{{'website_placeholder' | t}}", ng: { model: 'enterprise.website' } } + .row + .small-12.columns + .field + %label{ for: 'enterprise_facebook' } {{'facebook' | t}}: + %input.chunky{ id: 'enterprise_facebook', placeholder: "{{'facebook_placeholder' | t}}", ng: { model: 'enterprise.facebook' } } + .row + .small-12.columns + .field + %label{ for: 'enterprise_linkedin' } {{'linkedin' | t}}: + %input.chunky{ id: 'enterprise_linkedin', placeholder: "{{'linkedin_placeholder' | t}}", ng: { model: 'enterprise.linkedin' } } + .small-12.large-5.columns + .row + .small-12.columns + .field + %label{ for: 'enterprise_twitter' } {{'twitter' | t}}: + %input.chunky{ id: 'enterprise_twitter', placeholder: "{{'twitter_placeholder' | t}}", ng: { model: 'enterprise.twitter' } } + .row + .small-12.columns + .field + %label{ for: 'enterprise_instagram' } {{'instagram' | t}}: + %input.chunky{ id: 'enterprise_instagram', placeholder: "{{'instagram_placeholder' | t}}", ng: { model: 'enterprise.instagram' } } + + .row.buttons + .small-12.columns + %input.button.secondary{ type: "button", value: "{{'back' | t}}", ng: { click: "select('images')" } } + %input.button.primary.right{ type: "submit", value: "{{'continue' | t}}" } diff --git a/app/views/registration/steps/_steps.html.haml b/app/views/registration/steps/_steps.html.haml new file mode 100644 index 0000000000..7ea0412929 --- /dev/null +++ b/app/views/registration/steps/_steps.html.haml @@ -0,0 +1,4 @@ +%script{ type: "text/ng-template", id: "registration/steps.html" } + .row#progress-bar + .small-12.medium-2.columns.item{ ng: { repeat: 'step in steps', class: "{active: (currentStep() == step),'show-for-medium-up': (currentStep() != step)}" } } + {{ $index+1 + ". " + step }} diff --git a/app/views/registration/steps/_type.html.haml b/app/views/registration/steps/_type.html.haml new file mode 100644 index 0000000000..4c93c441f4 --- /dev/null +++ b/app/views/registration/steps/_type.html.haml @@ -0,0 +1,48 @@ +%script{ type: "text/ng-template", id: "registration/type.html" } + .container#registration-type + + %ng-include{ src: "'registration/steps.html'" } + + .row + .small-12.columns + %header + %h2{ "ng-bind" => "'registration_type_headline' | t:{enterprise: enterprise.name}" } + %h4 + {{'registration_type_question' | t}} + + %form{ name: 'type', novalidate: true, ng: { controller: "RegistrationFormCtrl", submit: "create(type)" } } + .row#enterprise-types{ 'data-equalizer' => true, ng: { if: "::enterprise.type != 'own'" } } + .small-12.columns.field + .row + .small-12.medium-6.large-6.columns{ 'data-equalizer-watch' => true } + %a.btnpanel#producer-panel{ href: "#", ng: { click: "enterprise.is_primary_producer = true", class: "{selected: enterprise.is_primary_producer}" } } + %i.ofn-i_059-producer + %h4 {{'registration_type_producer' | t}} + + .small-12.medium-6.large-6.columns{ 'data-equalizer-watch' => true } + %a.btnpanel#hub-panel{ href: "#", ng: { click: "enterprise.is_primary_producer = false", class: "{selected: enterprise.is_primary_producer == false}" } } + %i.ofn-i_063-hub + %h4 {{'registration_type_no_producer' | t}} + + .row + .small-12.columns + %input.chunky{ id: 'enterprise_is_primary_producer', name: 'is_primary_producer', hidden: true, required: true, ng: { model: 'enterprise.is_primary_producer' } } + %span.error{ ng: { show: "type.is_primary_producer.$error.required && submitted" } } + {{'registration_type_error' | t}} + .row + .small-12.columns + .panel.callout + .left + %i.ofn-i_013-help + + %p {{'registration_type_producer_help' | t}} + .panel.callout + .left + %i.ofn-i_013-help + + %p {{'registration_type_no_producer_help' | t}} + + .row.buttons + .small-12.columns + %input.button.secondary{ type: "button", value: "{{'back' | t}}", ng: { click: "select('contact')" } } + %input.button.primary.right{ type: "submit", value: "{{'create_profile' | t}}" } diff --git a/app/views/spree/admin/orders/_invoice_table2.html.haml b/app/views/spree/admin/orders/_invoice_table2.html.haml new file mode 100644 index 0000000000..0941904d8b --- /dev/null +++ b/app/views/spree/admin/orders/_invoice_table2.html.haml @@ -0,0 +1,58 @@ +%table.order-summary{:width => "100%"} + %thead + %tr + %th{:align => "left"} + %h5= t(:invoice_column_item) + %th{:align => "right", :width => "15%"} + %h5= t(:invoice_column_qty) + %th{:align => "right", :width => "15%"} + %h5= @order.has_taxes_included ? t(:invoice_column_unit_price_with_taxes) : t(:invoice_column_unit_price_without_taxes) + %th{:align => "right", :width => "15%"} + %h5= @order.has_taxes_included ? t(:invoice_column_price_with_taxes) : t(:invoice_column_price_without_taxes) + - if @order.total_tax > 0 + %th{:align => "right", :width => "15%"} + %h5= t(:invoice_column_tax_rate) + %tbody + - @order.line_items.sort_by{ |li| li.product.name }.each do |item| + %tr + %td + = render 'spree/shared/line_item_name', line_item: item + %td{:align => "right"} + = item.quantity + %td{:align => "right"} + = item.single_display_amount_with_adjustments + %td{:align => "right"} + = item.display_amount_with_adjustments + - if @order.total_tax > 0 + %td{:align => "right"} + = display_line_item_tax_rates(item) + - checkout_adjustments_for(@order, exclude: [:line_item]).reject{ |a| a.amount == 0 }.reverse_each do |adjustment| + %tr + %td + %strong= "#{raw(adjustment.label)}" + %td{:align => "right"} + %td{:align => "right"} + %td{:align => "right"} + = adjustment.display_amount + - if @order.total_tax > 0 + %td{:align => "right"} + = display_adjustment_tax_rates(adjustment) + %tfoot + %tr + %td{:align => "right", :colspan => "3"} + %strong= @order.has_taxes_included ? t(:total_incl_tax) : t(:total_excl_tax) + %td{:align => "right", :colspan => "2"} + %strong= @order.has_taxes_included ? @order.display_total : display_checkout_total_less_tax(@order) + - display_checkout_taxes_hash(@order).each do |tax_rate, tax_value| + %tr + %td{:align => "right", :colspan => "3"} + = t(:tax_total, rate: tax_rate) + %td{:align => "right", :colspan => "2"} + = tax_value + %tr + %td{:align => "right", :colspan => "3"} + = @order.has_taxes_included ? t(:total_excl_tax) : t(:total_incl_tax) + %td{:align => "right", :colspan => "2"} + = @order.has_taxes_included ? display_checkout_total_less_tax(@order) : @order.display_total +%p + diff --git a/app/views/spree/admin/orders/invoice.html.haml b/app/views/spree/admin/orders/invoice.html.haml index 0913ee27db..627032fd39 100644 --- a/app/views/spree/admin/orders/invoice.html.haml +++ b/app/views/spree/admin/orders/invoice.html.haml @@ -1,6 +1,5 @@ = wicked_pdf_stylesheet_link_tag "mail/all" - %table{:width => "100%"} %tbody %tr{ valign: "top" } @@ -49,4 +48,8 @@ %p +- if @order.distributor.invoice_text.present? + %p + = @order.distributor.invoice_text + = render 'spree/order_mailer/payment' diff --git a/app/views/spree/admin/orders/invoice2.html.haml b/app/views/spree/admin/orders/invoice2.html.haml new file mode 100644 index 0000000000..89f28ab308 --- /dev/null +++ b/app/views/spree/admin/orders/invoice2.html.haml @@ -0,0 +1,71 @@ += wicked_pdf_stylesheet_link_tag "mail/all" + + +%table{:width => "100%"} + %tbody + %tr{ valign: "top" } + %td{ :align => "left" } + %h4 + = t :tax_invoice + - if @order.distributor.display_invoice_logo? && @order.distributor.logo.present? + %td{ :align => "right", rowspan: 2 } + = wicked_pdf_image_tag @order.distributor.logo(:small), width: 150, height: 150 + %tr{ valign: "top" } + %td{ :align => "left" } + %strong= @order.distributor.name + %br + = @order.distributor.address.address_part1 + %br + = @order.distributor.address.address_part2 + %br + = @order.distributor.email_address + - if @order.distributor.phone.present? + %br + = @order.distributor.phone + - if @order.distributor.abn.present? + %br + = "#{t :abn} #{@order.distributor.abn}" + - if @order.distributor.acn.present? + %br + = "#{t :acn} #{@order.distributor.acn}" + %tr{ valign: "top" } + %td{ :align => "left", colspan: 2 } + %tr{ valign: "top" } + %td{ :align => "left" } + %br + = t :invoice_issued_on + = l Time.zone.now.to_date + %br + = t :date_of_transaction + = l @order.completed_at.to_date + %br + = t :order_number + = @order.number + %td{ :align => "right" } + = t :invoice_billing_address + %br + %strong= @order.ship_address.full_name + - if @order.customer.code.present? + %br + = "Code: #{@order.customer.code}" + %br + = @order.ship_address.address_part1 + %br + = @order.ship_address.address_part2 + += render 'spree/admin/orders/invoice_table2' + +- if @order.special_instructions.present? + %p.callout + %strong + = t :customer_instructions + %p + %em= @order.special_instructions + %p + + +- if @order.distributor.invoice_text.present? + %p + = @order.distributor.invoice_text + += render 'spree/order_mailer/payment' diff --git a/app/views/spree/admin/orders/ticket.html.haml b/app/views/spree/admin/orders/ticket.html.haml new file mode 100644 index 0000000000..53f224cff1 --- /dev/null +++ b/app/views/spree/admin/orders/ticket.html.haml @@ -0,0 +1,79 @@ +!!! Basic +%html + %head + + = javascript_include_tag "shared/jquery-1.8.0.js" + = javascript_include_tag "qz/qz-tray.js" + = javascript_include_tag "qz/sha-256.min.js" + = javascript_include_tag "qz/rsvp-3.1.0.min.js" + = javascript_include_tag "qz/jsrsasign-latest-all-min.js" + :javascript + var printData = [ + '\x1B' + '\x40', // init + '\x1B' + '\x74' + '\x10', + '\x1B' + '\x61' + '\x31', // center align + '\x1B' + '\x21' + '\x30', // em mode on + '#{@order.distributor.name}' + '\x0A', + '\x1B' + '\x21' + '\x0A' + '\x1B' + '\x45' + '\x0A', // em mode off + '\x0A', + '#{@order.distributor.address.address_part1}' + '\x0A', // text and line break + '#{@order.distributor.address.address_part2}' + '\x0A', + '#{@order.distributor.email}' + '\x0A', + '\x0A', // line break + '\x1B' + '\x61' + '\x32', // right align + '#{l Time.zone.now.to_date}' + '\x0A', + '#{@order.number}' + '\x0A', + '\x1B' + '\x61' + '\x30', // left align + '\x0A', + '\x1B' + '\x4D' + '\x31', // small text + "#{'%6s %-23s%12s%12s' % + [t(:ticket_column_qty), + t(:ticket_column_item), + t(:ticket_column_unit_price), + t(:ticket_column_total_price)]}", + '\x0A', + '\x1B' + '\x4D' + '\x30', // normal text + '__________________________________________' + '\x0A', + "#{@order.line_items + .sort_by{ |line_item| line_item.product.name } + .map { |line_item| '%5d %-19.19s%8.8s%8.8s' % + [line_item.quantity, + line_item.product.name, + line_item.single_display_amount_with_adjustments.money.format(symbol: false), + line_item.display_amount_with_adjustments.money.format(symbol: false)] } + .join('" + \'\x0A\' + "')}", + '\x0A', + "#{checkout_adjustments_for(@order, exclude: [:line_item]) + .reject{ |a| a.amount == 0 } + .reverse.map { |adjustment| '%5s %-27.27s%8.8s' % + ["", + raw(adjustment.label), + display_adjustment_amount(adjustment).money.format(symbol: false)] } + .join('" + \'\x0A\' + "')}", + '\x0A', + '__________________________________________' + '\x0A', + '\x0A', + '\x1B' + '\x45' + '\x0D', // bold on + "#{'%31s%10s' % + [t(:total_incl_tax), + @order.display_total]}", + '\x1B' + '\x45' + '\x0A', // bold off + '\x0A', + "#{display_checkout_taxes_hash(@order).map { |tax_rate, tax_value| + '%31s%10s' % + [t(:tax_total, rate: tax_rate), + tax_value] } + .join('" + \'\x0A\' + "')}", + '\x0A', + "#{'%31s%10s' % + [t(:total_excl_tax), + display_checkout_total_less_tax(@order)]}", + '\x0A', + '\x0A' + '\x0A' + '\x0A' + '\x0A' + '\x0A' + '\x0A' + '\x0A', + '\x1B' + '\x69', // cut paper + ]; + = javascript_include_tag "qz/ticket-popup.js" + %body + %div#printer-list + + diff --git a/app/views/spree/admin/products/bulk_edit/_header.html.haml b/app/views/spree/admin/products/bulk_edit/_header.html.haml index 09586b3e7c..8284ada662 100644 --- a/app/views/spree/admin/products/bulk_edit/_header.html.haml +++ b/app/views/spree/admin/products/bulk_edit/_header.html.haml @@ -1,5 +1,5 @@ - content_for :page_title do - = "Bulk Edit Products" + = t('.title') - content_for :page_actions do %div{ :class => "toolbar", 'data-hook' => "toolbar" } diff --git a/app/views/spree/admin/products/bulk_edit/_indicators.html.haml b/app/views/spree/admin/products/bulk_edit/_indicators.html.haml index 4760dacaeb..bfdd104690 100644 --- a/app/views/spree/admin/products/bulk_edit/_indicators.html.haml +++ b/app/views/spree/admin/products/bulk_edit/_indicators.html.haml @@ -3,14 +3,14 @@ %div.sixteen.columns.alpha#loading{ 'ng-if' => 'loading' } %img.spinner{ src: "/assets/spinning-circles.svg" } - %h1 LOADING PRODUCTS + %h1= t('.title') %div.sixteen.columns.alpha{ 'ng-show' => '!loading && filteredProducts.length == 0 && query.length==0' } - %h1#no_results No products yet. Why don't you add some? + %h1#no_results= t('.no_products') %div.sixteen.columns.alpha{ 'ng-show' => '!loading && filteredProducts.length == 0 && query.length!=0' } - %h1#no_results - Sorry, no results match + %h1#no_results + = t('.no_results') ' {{query}} ' \ No newline at end of file diff --git a/app/views/spree/admin/reports/_sales_tax_description.html.haml b/app/views/spree/admin/reports/_sales_tax_description.html.haml new file mode 100644 index 0000000000..5f4f7f6dfd --- /dev/null +++ b/app/views/spree/admin/reports/_sales_tax_description.html.haml @@ -0,0 +1,4 @@ +%ul{style: "margin-left: 12pt"} + - report_types.each do |report_type| + %li + = link_to report_type[0], "#{sales_tax_admin_reports_url}?report_type=#{report_type[1]}" diff --git a/app/views/spree/admin/reports/sales_tax.html.haml b/app/views/spree/admin/reports/sales_tax.html.haml index 9a5cb9e533..c90603d001 100644 --- a/app/views/spree/admin/reports/sales_tax.html.haml +++ b/app/views/spree/admin/reports/sales_tax.html.haml @@ -5,9 +5,15 @@ .four.columns.alpha = label_tag nil, t(:report_distributor) = f.collection_select(:distributor_id_eq, @distributors, :id, :name, {:include_blank => 'All'}, {:class => "select2 fullwidth"}) + = label_tag nil, t(:report_customers_type) + %br + = select_tag(:report_type, options_for_select([[t(:report_tax_types),:tax_types],[t(:report_tax_rates),:tax_rates]], @report_type)) + %br + %br = check_box_tag :csv = label_tag :csv, t(:report_customers_csv) %br + %br = button t(:search) %br diff --git a/app/views/spree/admin/variants/_autocomplete.js.erb b/app/views/spree/admin/variants/_autocomplete.js.erb index 41b0e84550..ccd93d63f7 100644 --- a/app/views/spree/admin/variants/_autocomplete.js.erb +++ b/app/views/spree/admin/variants/_autocomplete.js.erb @@ -9,11 +9,10 @@