diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 4abfdc4d3a..b0b1d1447c 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -1,6 +1,6 @@ # This configuration was generated by # `rubocop --auto-gen-config --auto-gen-only-exclude --exclude-limit 1400 --no-auto-gen-timestamp` -# using RuboCop version 1.50.2. +# using RuboCop version 1.51.0. # The point is for the user to remove these configuration records # one by one as the offenses are removed from the code base. # Note that changes in the inspected code, or installation of new @@ -100,7 +100,7 @@ Layout/FirstHashElementIndentation: Exclude: - 'spec/services/products_renderer_spec.rb' -# Offense count: 11 +# Offense count: 10 # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: AllowMultipleStyles, EnforcedHashRocketStyle, EnforcedColonStyle, EnforcedLastArgumentHashStyle. # SupportedHashRocketStyles: key, separator, table @@ -109,7 +109,6 @@ Layout/FirstHashElementIndentation: Layout/HashAlignment: Exclude: - 'app/controllers/spree/users_controller.rb' - - 'app/models/spree/image.rb' - 'spec/migrations/migrate_customer_names_spec.rb' - 'spec/models/enterprise_spec.rb' - 'spec/system/admin/customers_spec.rb' @@ -142,7 +141,7 @@ Layout/LeadingCommentSpace: Exclude: - 'spec/system/admin/enterprises_spec.rb' -# Offense count: 114 +# Offense count: 115 # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyle. # SupportedStyles: space, no_space @@ -199,12 +198,13 @@ Layout/LineEndStringConcatenationIndentation: - 'spec/system/consumer/cookies_spec.rb' - 'spec/system/consumer/shopping/cart_spec.rb' -# Offense count: 615 +# Offense count: 643 # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: Max, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, AllowedPatterns. # URISchemes: http, https Layout/LineLength: Exclude: + - 'app/components/confirm_modal_component.rb' - 'app/controllers/admin/bulk_line_items_controller.rb' - 'app/controllers/admin/enterprise_fees_controller.rb' - 'app/controllers/admin/enterprise_relationships_controller.rb' @@ -367,6 +367,8 @@ Layout/LineLength: - 'spec/system/admin/adjustments_spec.rb' - 'spec/system/admin/bulk_order_management_spec.rb' - 'spec/system/admin/bulk_product_update_spec.rb' + - 'spec/system/admin/order_spec.rb' + - 'spec/system/admin/product_import_spec.rb' # Offense count: 1 # This cop supports safe autocorrection (--autocorrect). @@ -412,7 +414,7 @@ Layout/TrailingEmptyLines: Exclude: - 'Rakefile' -# Offense count: 70 +# Offense count: 73 # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: AllowInHeredoc. Layout/TrailingWhitespace: @@ -420,7 +422,6 @@ Layout/TrailingWhitespace: - 'app/controllers/spree/users_controller.rb' - 'app/controllers/user_confirmations_controller.rb' - 'app/models/enterprise.rb' - - 'app/models/spree/image.rb' - 'spec/controllers/spree/credit_cards_controller_spec.rb' - 'spec/controllers/user_confirmations_controller_spec.rb' - 'spec/factories/order_factory.rb' @@ -438,7 +439,6 @@ Layout/TrailingWhitespace: - 'spec/system/admin/order_spec.rb' - 'spec/system/admin/product_import_spec.rb' - 'spec/system/admin/shipping_methods_spec.rb' - - 'spec/system/consumer/split_checkout_spec.rb' # Offense count: 7 # This cop supports safe autocorrection (--autocorrect). @@ -468,7 +468,7 @@ Lint/ConstantDefinitionInBlock: - 'spec/validators/date_time_string_validator_spec.rb' - 'spec/validators/integer_array_validator_spec.rb' -# Offense count: 8 +# Offense count: 6 # Configuration parameters: IgnoreLiteralBranches, IgnoreConstantBranches. Lint/DuplicateBranch: Exclude: @@ -581,6 +581,7 @@ Lint/UselessMethodDefinition: - 'app/models/spree/gateway.rb' # Offense count: 3 +# This cop supports safe autocorrection (--autocorrect). # Configuration parameters: CheckForMethodsWithNoSideEffects. Lint/Void: Exclude: @@ -651,7 +652,7 @@ Metrics/BlockNesting: Exclude: - 'app/models/spree/payment/processing.rb' -# Offense count: 46 +# Offense count: 47 # Configuration parameters: CountComments, Max, CountAsOne. Metrics/ClassLength: Exclude: @@ -659,7 +660,6 @@ Metrics/ClassLength: - 'app/controllers/admin/enterprise_fees_controller.rb' - 'app/controllers/admin/enterprises_controller.rb' - 'app/controllers/admin/order_cycles_controller.rb' - - 'app/controllers/admin/product_import_controller.rb' - 'app/controllers/admin/resource_controller.rb' - 'app/controllers/admin/schedules_controller.rb' - 'app/controllers/admin/subscriptions_controller.rb' @@ -704,7 +704,7 @@ Metrics/ClassLength: - 'lib/reporting/reports/enterprise_fee_summary/scope.rb' - 'lib/reporting/reports/xero_invoices/base.rb' -# Offense count: 35 +# Offense count: 36 # Configuration parameters: AllowedMethods, AllowedPatterns, Max. Metrics/CyclomaticComplexity: Exclude: @@ -759,7 +759,7 @@ Metrics/MethodLength: - 'lib/reporting/reports/xero_invoices/base.rb' - 'lib/tasks/sample_data/product_factory.rb' -# Offense count: 50 +# Offense count: 49 # Configuration parameters: CountComments, Max, CountAsOne. Metrics/ModuleLength: Exclude: @@ -808,16 +808,16 @@ Metrics/ModuleLength: - 'spec/models/spree/product_spec.rb' - 'spec/models/spree/shipping_method_spec.rb' - 'spec/models/spree/tax_rate_spec.rb' - - 'spec/models/spree/variant_spec.rb' - 'spec/services/permissions/order_spec.rb' - 'spec/services/variant_units/option_value_namer_spec.rb' - 'spec/support/request/shop_workflow.rb' - 'spec/support/request/stripe_stubs.rb' -# Offense count: 7 +# Offense count: 8 # Configuration parameters: Max, CountKeywordArgs, MaxOptionalParameters. Metrics/ParameterLists: Exclude: + - 'app/components/confirm_modal_component.rb' - 'app/helpers/angular_form_builder.rb' - 'app/models/product_import/entry_processor.rb' - 'lib/reporting/reports/xero_invoices/base.rb' @@ -852,6 +852,7 @@ Naming/HeredocDelimiterNaming: - 'app/models/content_configuration.rb' # Offense count: 5 +# This cop supports unsafe autocorrection (--autocorrect-all). # Configuration parameters: EnforcedStyleForLeadingUnderscores. # SupportedStylesForLeadingUnderscores: disallowed, required, optional Naming/MemoizedInstanceVariableName: @@ -930,12 +931,6 @@ Rails/ApplicationController: Exclude: - 'engines/dfc_provider/app/controllers/dfc_provider/base_controller.rb' -# Offense count: 1 -# This cop supports unsafe autocorrection (--autocorrect-all). -Rails/ApplicationJob: - Exclude: - - 'app/jobs/report_job.rb' - # Offense count: 5 # This cop supports unsafe autocorrection (--autocorrect-all). # Configuration parameters: NilOrEmpty, NotPresent, UnlessPresent. @@ -1083,7 +1078,6 @@ Rails/InverseOf: Exclude: - 'app/models/enterprise.rb' - 'app/models/order_cycle.rb' - - 'app/models/spree/adjustment.rb' - 'app/models/spree/country.rb' - 'app/models/spree/inventory_unit.rb' - 'app/models/spree/line_item.rb' @@ -1122,7 +1116,7 @@ Rails/LexicallyScopedActionFilter: - 'app/controllers/spree/admin/zones_controller.rb' - 'app/controllers/spree/users_controller.rb' -# Offense count: 9 +# Offense count: 8 # This cop supports unsafe autocorrection (--autocorrect-all). Rails/NegateInclude: Exclude: @@ -1131,11 +1125,10 @@ Rails/NegateInclude: - 'app/models/product_import/spreadsheet_entry.rb' - 'app/models/spree/order/checkout.rb' - 'app/services/order_cart_reset.rb' - - 'engines/order_management/app/services/order_management/stock/estimator.rb' - 'lib/spree/localized_number.rb' - 'spec/support/matchers/table_matchers.rb' -# Offense count: 18 +# Offense count: 17 Rails/OutputSafety: Exclude: - 'app/helpers/angular_form_helper.rb' @@ -1180,7 +1173,7 @@ Rails/PluckInWhere: Exclude: - 'app/models/spree/variant.rb' -# Offense count: 28 +# Offense count: 30 # This cop supports unsafe autocorrection (--autocorrect-all). Rails/RedundantPresenceValidationOnBelongsTo: Exclude: @@ -1690,7 +1683,7 @@ Style/RedundantStringEscape: - 'spec/controllers/spree/admin/shipping_methods_controller_spec.rb' - 'spec/system/admin/enterprise_fees_spec.rb' -# Offense count: 206 +# Offense count: 208 Style/Send: Exclude: - 'app/controllers/split_checkout_controller.rb' @@ -1740,7 +1733,7 @@ Style/SlicingWithRange: - 'engines/order_management/app/services/order_management/subscriptions/validator.rb' - 'lib/discourse/single_sign_on.rb' -# Offense count: 29 +# Offense count: 28 # This cop supports unsafe autocorrection (--autocorrect-all). # Configuration parameters: Mode. Style/StringConcatenation: @@ -1761,7 +1754,6 @@ Style/StringConcatenation: - 'lib/spree/core/environment_extension.rb' - 'spec/models/spree/line_item_spec.rb' - 'spec/models/spree/product_spec.rb' - - 'spec/models/spree/variant_spec.rb' - 'spec/services/embedded_page_service_spec.rb' - 'spec/support/api_helper.rb' - 'spec/support/features/datepicker_helper.rb' diff --git a/app/assets/javascripts/admin/all.js b/app/assets/javascripts/admin/all.js index 0f0643d388..739dff3f73 100644 --- a/app/assets/javascripts/admin/all.js +++ b/app/assets/javascripts/admin/all.js @@ -7,7 +7,6 @@ // jquery and angular //= require jquery2 -//= require jquery_ujs //= require jquery.ui.all //= require jquery.powertip //= require jquery.cookie diff --git a/app/assets/javascripts/admin/orders/controllers/bulk_invoice_controller.js.coffee b/app/assets/javascripts/admin/orders/controllers/bulk_invoice_controller.js.coffee deleted file mode 100644 index cd6a02d40b..0000000000 --- a/app/assets/javascripts/admin/orders/controllers/bulk_invoice_controller.js.coffee +++ /dev/null @@ -1,32 +0,0 @@ -angular.module("admin.orders").controller "bulkInvoiceCtrl", ($scope, $http, $timeout) -> - $scope.createBulkInvoice = -> - $scope.invoice_id = null - $scope.poll = 1 - $scope.loading = true - $scope.message = null - $scope.error = null - $scope.poll_wait = 5 # 5 Seconds between each check - $scope.poll_retries = 80 # Maximum checks before stopping - - $http.post('/admin/orders/invoices', {order_ids: $scope.selected_orders}).then (response) -> - $scope.invoice_id = response.data - $scope.pollBulkInvoice() - - $scope.pollBulkInvoice = -> - $timeout($scope.nextPoll, $scope.poll_wait * 1000) - - $scope.nextPoll = -> - $http.get('/admin/orders/invoices/'+$scope.invoice_id+'/poll').then (response) -> - $scope.loading = false - $scope.message = t('js.admin.orders.index.bulk_invoice_created') - - .catch (response) -> - $scope.poll++ - - if $scope.poll > $scope.poll_retries - $scope.loading = false - $scope.error = t('js.admin.orders.index.bulk_invoice_failed') - return - - $scope.pollBulkInvoice() - diff --git a/app/assets/javascripts/admin/orders/controllers/orders_controller.js.coffee b/app/assets/javascripts/admin/orders/controllers/orders_controller.js.coffee deleted file mode 100644 index 95486ce19d..0000000000 --- a/app/assets/javascripts/admin/orders/controllers/orders_controller.js.coffee +++ /dev/null @@ -1,117 +0,0 @@ -angular.module("admin.orders").controller "ordersCtrl", ($scope, $timeout, RequestMonitor, Orders, SortOptions, $window, $filter, $location, KeyValueMapStore) -> - $scope.RequestMonitor = RequestMonitor - $scope.pagination = Orders.pagination - $scope.orders = Orders.all - $scope.sortOptions = SortOptions - $scope.per_page_options = [ - {id: 15, name: t('js.admin.orders.index.per_page', results: 15)}, - {id: 50, name: t('js.admin.orders.index.per_page', results: 50)}, - {id: 100, name: t('js.admin.orders.index.per_page', results: 100)} - ] - $scope.selected_orders = [] - $scope.checkboxes = {} - $scope.selected = false - $scope.select_all = false - $scope.poll = 0 - $scope.rowStatus = {} - - KeyValueMapStore.localStorageKey = 'ordersFilters' - KeyValueMapStore.storableKeys = ["q", "sorting", "page", "per_page"] - - $scope.initialise = -> - unless KeyValueMapStore.restoreValues($scope) - $scope.setDefaults() - - $scope.fetchResults() - - $scope.setDefaults = -> - $scope.per_page = 15 - $scope.q = { - completed_at_not_null: true - } - e = new CustomEvent("flatpickr_clear"); - window.dispatchEvent(e) - - $scope.clearFilters = () -> - KeyValueMapStore.clearKeyValueMap() - $scope.setDefaults() - $scope.fetchResults() - - $scope.fetchResults = (page=1) -> - startDateWithTime = $scope.appendStringIfNotEmpty($scope.q?.completed_at_gteq, ' 00:00:00') - endDateWithTime = $scope.appendStringIfNotEmpty($scope.q?.completed_at_lteq, ' 23:59:59') - - $scope.resetSelected() - params = { - 'q[completed_at_gteq]': startDateWithTime, - 'q[completed_at_lteq]': endDateWithTime, - 'q[state_eq]': $scope.q?.state_eq, - 'q[number_cont]': $scope.q?.number_cont, - 'q[email_cont]': $scope.q?.email_cont, - 'q[bill_address_firstname_start]': $scope.q?.bill_address_firstname_start, - 'q[bill_address_lastname_start]': $scope.q?.bill_address_lastname_start, - # Set default checkbox values to null. See: https://github.com/openfoodfoundation/openfoodnetwork/pull/3076#issuecomment-440010498 - 'q[completed_at_not_null]': $scope.q?.completed_at_not_null || null, - 'q[distributor_id_in][]': $scope.q?.distributor_id_in, - 'q[order_cycle_id_in][]': $scope.q?.order_cycle_id_in, - 'q[s]': $scope.sorting || 'completed_at desc', - shipping_method_id: $scope.q?.shipping_method_id, - per_page: $scope.per_page, - page: page - } - KeyValueMapStore.setStoredValues($scope) - RequestMonitor.load(Orders.index(params).$promise) - - $scope.appendStringIfNotEmpty = (baseString, stringToAppend) -> - return baseString unless baseString - return baseString if baseString.endsWith(stringToAppend) - - baseString + stringToAppend - - $scope.resetSelected = -> - $scope.selected_orders.length = 0 - $scope.selected = false - $scope.select_all = false - $scope.checkboxes = {} - - $scope.toggleSelection = (id) -> - index = $scope.selected_orders.indexOf(id) - - if index == -1 - $scope.selected_orders.push(id) - else - $scope.selected_orders.splice(index, 1) - - $scope.toggleAll = -> - $scope.selected_orders.length = 0 - $scope.orders.forEach (order) -> - $scope.checkboxes[order.id] = $scope.select_all - $scope.selected_orders.push order.id if $scope.select_all - - $scope.$watch 'sortOptions', (sort) -> - return unless sort && sort.predicate != "" - - $scope.sorting = sort.getSortingExpr() - $scope.fetchResults() - , true - - $scope.capturePayment = (order) -> - $scope.rowAction('capture', order) - - $scope.shipOrder = (order) -> - $scope.rowAction('ship', order) - - $scope.rowAction = (action, order) -> - $scope.rowStatus[order.id] = "loading" - - Orders[action](order).$promise.then (data) -> - $scope.rowStatus[order.id] = "success" - $timeout(-> - $scope.rowStatus[order.id] = null - , 1500) - , (error) -> - $scope.rowStatus[order.id] = "error" - - $scope.changePage = (newPage) -> - $scope.page = newPage - $scope.fetchResults(newPage) diff --git a/app/assets/javascripts/admin/orders/directives/invoices_modal.js.coffee b/app/assets/javascripts/admin/orders/directives/invoices_modal.js.coffee deleted file mode 100644 index 0f2eabe778..0000000000 --- a/app/assets/javascripts/admin/orders/directives/invoices_modal.js.coffee +++ /dev/null @@ -1,5 +0,0 @@ -angular.module("admin.orders").directive "invoicesModal", ($modal) -> - restrict: 'C' - link: (scope, elem, attrs, ctrl) -> - elem.on "click", (ev) => - scope.uploadModal = $modal.open(templateUrl: 'admin/modals/bulk_invoice.html', controller: ctrl, scope: scope, windowClass: 'simple-modal') diff --git a/app/assets/javascripts/admin_minimal.js b/app/assets/javascripts/admin_minimal.js new file mode 100644 index 0000000000..2a6b52ddac --- /dev/null +++ b/app/assets/javascripts/admin_minimal.js @@ -0,0 +1,34 @@ +// This is a manifest file that'll be compiled into including all the files listed below. +// Add new JavaScript/Coffee code in separate files in this directory and they'll automatically +// be included in the compiled file accessible from http://example.com/assets/application.js +// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the +// the compiled file. +// + +//= require jquery2 +//= require admin/spree/spree-select2 +//= require admin/spree/handlebar_extensions + +//= require i18n/translations +//= require darkswarm/i18n.translate.js +//= require moment/min/moment.min.js +//= require moment/locale/ar.js +//= require moment/locale/ca.js +//= require moment/locale/de.js +//= require moment/locale/en-gb.js +//= require moment/locale/es.js +//= require moment/locale/fil.js +//= require moment/locale/fr.js +//= require moment/locale/it.js +//= require moment/locale/nb.js +//= require moment/locale/nl-be.js +//= require moment/locale/pt-br.js +//= require moment/locale/pt.js +//= require moment/locale/ru.js +//= require moment/locale/sv.js +//= require moment/locale/tr.js +//= require moment/locale/pl.js + +//= require js-big-decimal/dist/web/js-big-decimal.min.js + +window.angular = { module: function(noop){ return { value: function(){} } } } \ No newline at end of file diff --git a/app/assets/javascripts/darkswarm/all.js.coffee b/app/assets/javascripts/darkswarm/all.js.coffee index dfaf65a185..0797cfd99b 100644 --- a/app/assets/javascripts/darkswarm/all.js.coffee +++ b/app/assets/javascripts/darkswarm/all.js.coffee @@ -67,11 +67,3 @@ document.addEventListener "turbo:before-render", -> rootscope = null window.injector = null true - -document.addEventListener "ajax:beforeSend", (event) => - window.Turbo.navigator.adapter.progressBar.setValue(0) - window.Turbo.navigator.adapter.progressBar.show() - -document.addEventListener "ajax:complete", (event) => - window.Turbo.navigator.adapter.progressBar.setValue(100) - window.Turbo.navigator.adapter.progressBar.hide() diff --git a/app/assets/javascripts/templates/admin/links_dropdown.html.haml b/app/assets/javascripts/templates/admin/links_dropdown.html.haml index 1f4f8e4f47..afcaa1e8da 100644 --- a/app/assets/javascripts/templates/admin/links_dropdown.html.haml +++ b/app/assets/javascripts/templates/admin/links_dropdown.html.haml @@ -4,7 +4,16 @@ {{ 'admin.actions' | t }} %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}}" } } - %span - %i{ ng: { class: "link.icon" } } - %span {{ link.name }} + %div{ 'ng-repeat' => "link in links" } + %a.menu_item{ 'ng-if': "link.method", href: '{{link.url}}', target: "{{link.target || '_self'}}", data: { method: "{{ link.method }}", "ujs-navigate": "false", confirm: "{{link.confirm}}" } } + %span + %i{ ng: { class: "link.icon" } } + %span {{ link.name }} + %a.menu_item{ 'ng-if': "link.confirm && !link.method", href: '{{link.url}}', target: "{{link.target || '_self'}}", "data-confirm": "{{link.confirm}}" } + %span + %i{ ng: { class: "link.icon" } } + %span {{ link.name }} + %a.menu_item{ 'ng-if': "!link.confirm && !link.method", href: '{{link.url}}', target: "{{link.target || '_self'}}" } + %span + %i{ ng: { class: "link.icon" } } + %span {{ link.name }} diff --git a/app/channels/session_channel.rb b/app/channels/session_channel.rb new file mode 100644 index 0000000000..be7d418860 --- /dev/null +++ b/app/channels/session_channel.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +class SessionChannel < ApplicationCable::Channel + def self.for_request(request) + "SessionChannel:#{request.session.id}" + end + + def subscribed + return reject if current_user.nil? + + stream_from "SessionChannel:#{session_id}" + end +end diff --git a/app/components/confirm_modal_component.rb b/app/components/confirm_modal_component.rb index 3a73af0e68..4fd17dc908 100644 --- a/app/components/confirm_modal_component.rb +++ b/app/components/confirm_modal_component.rb @@ -1,11 +1,12 @@ # frozen_string_literal: true class ConfirmModalComponent < ModalComponent - def initialize(id:, confirm_actions: nil, controllers: nil, message: nil, confirm_reflexes: nil) + def initialize(id:, confirm_actions: nil, reflex: nil, controller: nil, message: nil, confirm_reflexes: nil) super(id: id, close_button: true) @confirm_actions = confirm_actions + @reflex = reflex @confirm_reflexes = confirm_reflexes - @controllers = controllers + @controller = controller @message = message end diff --git a/app/components/confirm_modal_component/confirm_modal_component.html.haml b/app/components/confirm_modal_component/confirm_modal_component.html.haml index 0c507885ce..1b3e1ff217 100644 --- a/app/components/confirm_modal_component/confirm_modal_component.html.haml +++ b/app/components/confirm_modal_component/confirm_modal_component.html.haml @@ -1,4 +1,4 @@ -%div{ id: @id, "data-controller": "modal #{@controllers}", "data-action": "keyup@document->modal#closeIfEscapeKey" } +%div{ id: @id, "data-controller": "modal #{@controller}", "data-action": "keyup@document->modal#closeIfEscapeKey", "data-#{@controller}-reflex-value": @reflex } .reveal-modal-bg.fade{ "data-modal-target": "background", "data-action": "click->modal#close" } .reveal-modal.fade.tiny.help-modal{ "data-modal-target": "modal" } = content diff --git a/app/components/product_component/product_component.html.haml b/app/components/product_component/product_component.html.haml index e0d9d760a8..55c3e47e67 100644 --- a/app/components/product_component/product_component.html.haml +++ b/app/components/product_component/product_component.html.haml @@ -1,6 +1,6 @@ %tr - @columns.each do |column| %td.products_column{class: column[:id]} - - if column[:id] == "name" && @image + - if column[:id] == "name" && @image&.attachment.present? = image_tag @image.url(:mini) = column[:value] diff --git a/app/controllers/api/v0/orders_controller.rb b/app/controllers/api/v0/orders_controller.rb index 3f23a32e40..f36157db21 100644 --- a/app/controllers/api/v0/orders_controller.rb +++ b/app/controllers/api/v0/orders_controller.rb @@ -47,17 +47,15 @@ module Api def capture authorize! :admin, order - pending_payment = order.pending_payments.first + payment_capture = OrderCaptureService.new(order) - return payment_capture_failed unless order.payment_required? && pending_payment - - if pending_payment.capture! + if payment_capture.call render json: order.reload, serializer: Api::Admin::OrderSerializer, status: :ok + elsif payment_capture.gateway_error.present? + error_during_processing(payment_capture.gateway_error) else payment_capture_failed end - rescue Spree::Core::GatewayError => e - error_during_processing(e) end private diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 4c590b7792..3587072cc1 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -9,6 +9,7 @@ require 'spree/core/controller_helpers/common' require 'open_food_network/referer_parser' class ApplicationController < ActionController::Base + include CablecarResponses include Pagy::Backend include RequestTimeouts diff --git a/app/controllers/spree/admin/orders_controller.rb b/app/controllers/spree/admin/orders_controller.rb index 51a21a8b60..8f3e73bf9e 100644 --- a/app/controllers/spree/admin/orders_controller.rb +++ b/app/controllers/spree/admin/orders_controller.rb @@ -11,11 +11,18 @@ module Spree before_action :load_order, only: [:edit, :update, :fire, :resend, :invoice, :print, :distribution] before_action :load_distribution_choices, only: [:new, :edit, :update, :distribution] - before_action :require_distributor_abn, only: :invoice + before_action :restore_saved_query!, only: :index respond_to :html, :json + def index + orders = SearchOrders.new(search_params, spree_current_user).orders + @pagy, @orders = pagy(orders, items: params[:per_page] || 15) + + update_search_results if searching? + end + def new @order = Order.create @order.created_by = spree_current_user @@ -110,6 +117,36 @@ module Spree private + def update_search_results + session[:admin_orders_search] = search_params + + render cable_ready: cable_car.inner_html( + "#orders-index", + partial("spree/admin/orders/table", locals: { pagy: @pagy, orders: @orders }) + ) + end + + def searching? + params[:q].present? && request.format.symbol == :cable_ready + end + + def search_params + default_filters.deep_merge( + params.permit(:page, :per_page, :shipping_method_id, q: {}) + ).to_h.with_indifferent_access + end + + def default_filters + { q: { completed_at_not_null: 1, s: "completed_at desc" } } + end + + def restore_saved_query! + return unless request.format.html? + + @_params = ActionController::Parameters.new(session[:admin_orders_search] || {}) + @stored_query = search_params.to_query + end + def on_update @order.recreate_all_fees! diff --git a/app/helpers/spree/admin/orders_helper.rb b/app/helpers/spree/admin/orders_helper.rb index 9032f7b787..81f9066f90 100644 --- a/app/helpers/spree/admin/orders_helper.rb +++ b/app/helpers/spree/admin/orders_helper.rb @@ -62,7 +62,6 @@ module Spree { name: t(:resend_confirmation), url: spree.resend_admin_order_path(@order), icon: 'icon-email', - method: 'post', confirm: t(:confirm_resend_order_confirmation) } end diff --git a/app/jobs/bulk_invoice_job.rb b/app/jobs/bulk_invoice_job.rb index 0957ef393a..324554733d 100644 --- a/app/jobs/bulk_invoice_job.rb +++ b/app/jobs/bulk_invoice_job.rb @@ -1,7 +1,10 @@ # frozen_string_literal: true class BulkInvoiceJob < ApplicationJob - def perform(order_ids, filepath) + include CableReady::Broadcaster + delegate :render, to: ActionController::Base + + def perform(order_ids, filepath, options = {}) pdf = CombinePDF.new sorted_orders(order_ids).each do |order| @@ -11,6 +14,8 @@ class BulkInvoiceJob < ApplicationJob end pdf.save filepath + + broadcast(filepath, options[:channel]) if options[:channel] end private @@ -18,10 +23,22 @@ class BulkInvoiceJob < ApplicationJob # Ensures the records are returned in the same order the ids were originally given in def sorted_orders(order_ids) orders_by_id = Spree::Order.where(id: order_ids).to_a.index_by(&:id) - order_ids.map { |id| orders_by_id[id] } + order_ids.map { |id| orders_by_id[id.to_i] } end def renderer @renderer ||= InvoiceRenderer.new end + + def broadcast(filepath, channel) + file_id = filepath.split("/").last.split(".").first + + cable_ready[channel]. + inner_html( + selector: "#bulk_invoices_modal .modal-content", + html: render(partial: "spree/admin/orders/bulk/invoice_link", + locals: { invoice_url: "/admin/orders/invoices/#{file_id}" }) + ). + broadcast + end end diff --git a/app/reflexes/admin/orders_reflex.rb b/app/reflexes/admin/orders_reflex.rb new file mode 100644 index 0000000000..7e722a2705 --- /dev/null +++ b/app/reflexes/admin/orders_reflex.rb @@ -0,0 +1,101 @@ +# frozen_string_literal: true + +module Admin + class OrdersReflex < ApplicationReflex + before_reflex :authorize_order, only: [:capture, :ship] + + def capture + payment_capture = OrderCaptureService.new(@order) + + if payment_capture.call + morph dom_id(@order), render(partial: "spree/admin/orders/table_row", + locals: { order: @order.reload, success: true }) + else + flash[:error] = with_locale{ + payment_capture.gateway_error || I18n.t(:payment_processing_failed) + } + morph_admin_flashes + end + end + + def ship + if @order.ship + morph dom_id(@order), render(partial: "spree/admin/orders/table_row", + locals: { order: @order.reload, success: true }) + else + flash[:error] = with_locale{ I18n.t("api.orders.failed_to_update") } + morph_admin_flashes + end + end + + def bulk_invoice(params) + cable_ready.append( + selector: "#orders-index", + html: render(partial: "spree/admin/orders/bulk/invoice_modal") + ).broadcast + + BulkInvoiceJob.perform_later( + params[:bulk_ids], + "tmp/invoices/#{Time.zone.now.to_i}-#{SecureRandom.hex(2)}.pdf", + channel: SessionChannel.for_request(request) + ) + + morph :nothing + end + + def cancel_orders(params) + cancelled_orders = OrdersBulkCancelService.new(params, current_user).call + + cable_ready.dispatch_event(name: "modal:close") + + cancelled_orders.each do |order| + cable_ready.replace( + selector: dom_id(order), + html: render(partial: "spree/admin/orders/table_row", locals: { order: order }) + ) + end + + cable_ready.broadcast + morph :nothing + end + + def resend_confirmation_emails(params) + editable_orders.where(id: params[:bulk_ids]).find_each do |order| + next unless can? :resend, order + + Spree::OrderMailer.confirm_email_for_customer(order.id, true).deliver_later + end + + success("admin.resend_confirmation_emails_feedback", params[:bulk_ids].count) + end + + def send_invoices(params) + count = 0 + editable_orders.where(id: params[:bulk_ids]).find_each do |o| + next unless o.distributor.can_invoice? && (o.resumed? || o.complete?) + + Spree::OrderMailer.invoice_email(o.id).deliver_later + count += 1 + end + + success("admin.send_invoice_feedback", count) + end + + private + + def authorize_order + @order = Spree::Order.find_by(id: element.dataset[:id]) + authorize! :admin, @order + end + + def success(i18n_key, count) + flash[:success] = with_locale { I18n.t(i18n_key, count: count) } + cable_ready.dispatch_event(name: "modal:close") + morph_admin_flashes + end + + def editable_orders + Permissions::Order.new(current_user).editable_orders + end + end +end diff --git a/app/reflexes/application_reflex.rb b/app/reflexes/application_reflex.rb index ff41bf8288..4ed251f8bb 100644 --- a/app/reflexes/application_reflex.rb +++ b/app/reflexes/application_reflex.rb @@ -20,6 +20,8 @@ class ApplicationReflex < StimulusReflex::Reflex delegate :current_user, to: :connection + private + def current_ability Spree::Ability.new(current_user) end @@ -27,4 +29,8 @@ class ApplicationReflex < StimulusReflex::Reflex def with_locale(&block) I18n.with_locale(current_user.locale, &block) end + + def morph_admin_flashes + morph "#flashes", render(partial: "admin/shared/flashes", locals: { flashes: flash }) + end end diff --git a/app/reflexes/bulk_actions_in_orders_list_reflex.rb b/app/reflexes/bulk_actions_in_orders_list_reflex.rb deleted file mode 100644 index 03cff66633..0000000000 --- a/app/reflexes/bulk_actions_in_orders_list_reflex.rb +++ /dev/null @@ -1,35 +0,0 @@ -# frozen_string_literal: true - -class BulkActionsInOrdersListReflex < ApplicationReflex - def resend_confirmation_email(order_ids) - editable_orders.where(id: order_ids).find_each do |o| - Spree::OrderMailer.confirm_email_for_customer(o.id, true).deliver_later if can? :resend, o - end - - success("admin.resend_confirmation_emails_feedback", order_ids.count) - end - - def send_invoice(order_ids) - count = 0 - editable_orders.where(id: order_ids).find_each do |o| - next unless o.distributor.can_invoice? && (o.resumed? || o.complete?) - - Spree::OrderMailer.invoice_email(o.id).deliver_later - count += 1 - end - - success("admin.send_invoice_feedback", count) - end - - private - - def success(i18n_key, count) - flash[:success] = I18n.t(i18n_key, count: count) - cable_ready.dispatch_event(name: "modal:close") - morph "#flashes", render(partial: "shared/flashes", locals: { flashes: flash }) - end - - def editable_orders - Permissions::Order.new(current_user).editable_orders - end -end diff --git a/app/reflexes/cancel_orders_reflex.rb b/app/reflexes/cancel_orders_reflex.rb deleted file mode 100644 index 10876d018f..0000000000 --- a/app/reflexes/cancel_orders_reflex.rb +++ /dev/null @@ -1,9 +0,0 @@ -# frozen_string_literal: true - -class CancelOrdersReflex < ApplicationReflex - def confirm(params) - OrdersBulkCancelService.new(params, current_user).call - cable_ready.dispatch_event(name: "modal:close") - # flash[:success] = Spree.t(:order_updated) - end -end diff --git a/app/reflexes/white_label_reflex.rb b/app/reflexes/white_label_reflex.rb index 667ed98912..140079add6 100644 --- a/app/reflexes/white_label_reflex.rb +++ b/app/reflexes/white_label_reflex.rb @@ -21,6 +21,6 @@ class WhiteLabelReflex < ApplicationReflex I18n.t("admin.enterprises.form.white_label.remove_logo_success") } cable_ready.dispatch_event(name: "modal:close") - morph "#flashes", render(partial: "shared/flashes", locals: { flashes: flash }) + morph_admin_flashes end end diff --git a/app/services/order_capture_service.rb b/app/services/order_capture_service.rb new file mode 100644 index 0000000000..78e69c9a1d --- /dev/null +++ b/app/services/order_capture_service.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +# Use `authorize! :admin order` before calling this service + +class OrderCaptureService + attr_reader :gateway_error + + def initialize(order) + @order = order + @gateway_error = nil + end + + def call + return false unless @order.payment_required? + return false unless (pending_payment = @order.pending_payments.first) + + pending_payment.capture! + rescue Spree::Core::GatewayError => e + @gateway_error = e + false + end +end diff --git a/app/services/orders_bulk_cancel_service.rb b/app/services/orders_bulk_cancel_service.rb index 2f51709eeb..a788183ffc 100644 --- a/app/services/orders_bulk_cancel_service.rb +++ b/app/services/orders_bulk_cancel_service.rb @@ -2,14 +2,14 @@ class OrdersBulkCancelService def initialize(params, current_user) - @order_ids = params[:order_ids] + @order_ids = params[:bulk_ids] @current_user = current_user @send_cancellation_email = params[:send_cancellation_email] @restock_items = params[:restock_items] end def call - editable_orders.where(id: @order_ids).find_each do |order| + editable_orders.where(id: @order_ids).each do |order| order.send_cancellation_email = @send_cancellation_email order.restock_items = @restock_items order.cancel diff --git a/app/services/search_orders.rb b/app/services/search_orders.rb index 6b08d78cfb..60cf824e63 100644 --- a/app/services/search_orders.rb +++ b/app/services/search_orders.rb @@ -26,7 +26,7 @@ class SearchOrders base_query = ::Permissions::Order.new(current_user).editable_orders.not_empty .or(::Permissions::Order.new(current_user).editable_orders.finalized) - return base_query unless params[:shipping_method_id] + return base_query if params[:shipping_method_id].blank? base_query .joins(shipments: :shipping_rates) diff --git a/app/views/admin/enterprises/form/_stripe_connect.html.haml b/app/views/admin/enterprises/form/_stripe_connect.html.haml index 5c42499718..ec8e1e178b 100644 --- a/app/views/admin/enterprises/form/_stripe_connect.html.haml +++ b/app/views/admin/enterprises/form/_stripe_connect.html.haml @@ -4,7 +4,8 @@ .row = t('.stripe_account_connected') .row - =link_to t('.disconnect'), main_app.admin_stripe_account_path(@stripe_account), method: :delete, class: 'button' + + =link_to t('.disconnect'), main_app.admin_stripe_account_path(@stripe_account), data: { method: :delete, "ujs-navigate": "false"}, class: 'button' - else .row.stripe-info .six.columns.alpha diff --git a/app/views/admin/oidc_settings/index.html.haml b/app/views/admin/oidc_settings/index.html.haml index 4a6878eed6..eed72c78d2 100644 --- a/app/views/admin/oidc_settings/index.html.haml +++ b/app/views/admin/oidc_settings/index.html.haml @@ -22,4 +22,4 @@ %br = button_to t(".link_account_button"), Spree::Core::Engine.routes.url_helpers.spree_user_openid_connect_omniauth_authorize_path(auth_type: "login"), - method: :post + data: { method: :post, "ujs-navigate": "false" } diff --git a/app/views/admin/order_cycles/_row.html.haml b/app/views/admin/order_cycles/_row.html.haml index 5a2e06dbb6..4508858a1d 100644 --- a/app/views/admin/order_cycles/_row.html.haml +++ b/app/views/admin/order_cycles/_row.html.haml @@ -36,4 +36,4 @@ %td.actions{ ng: { if: 'orderCycle.viewing_as_coordinator' } } %a.clone-order-cycle.icon-copy.no-text{ ng: { href: '{{orderCycle.clone_path}}'}, 'ofn-with-tip' => t(:clone) } %td.actions{ ng: { if: 'orderCycle.deletable && orderCycle.viewing_as_coordinator' }} - %a.delete-order-cycle.icon-trash.no-text{ ng: { href: '{{orderCycle.delete_path}}'}, data: { method: 'delete', confirm: t(:are_you_sure) }, 'ofn-with-tip' => t(:remove) } + %a.delete-order-cycle.icon-trash.no-text{ ng: { href: '{{orderCycle.delete_path}}'}, data: { method: 'delete', confirm: t(:are_you_sure), "ujs-navigate": "false" }, 'ofn-with-tip' => t(:remove) } diff --git a/app/views/admin/order_cycles/checkout_options.html.haml b/app/views/admin/order_cycles/checkout_options.html.haml index 80d58be8c6..cc43c1323e 100644 --- a/app/views/admin/order_cycles/checkout_options.html.haml +++ b/app/views/admin/order_cycles/checkout_options.html.haml @@ -21,11 +21,11 @@ = hidden_field_tag "order_cycle[selected_distributor_shipping_method_ids][]", "" - @order_cycle.distributors.each do |distributor| - distributor_shipping_methods = @order_cycle.attachable_distributor_shipping_methods.where("distributor_id = ?", distributor.id).includes(:shipping_method) - %tr{ class: "distributor-#{distributor.id}-shipping-methods", "data-controller": "select-all" } + %tr{ class: "distributor-#{distributor.id}-shipping-methods", "data-controller": "checked" } %td.text-center - if distributor_shipping_methods.many? %label - = check_box_tag nil, nil, nil, { "data-action": "change->select-all#toggleAll", "data-select-all-target": "all" } + = check_box_tag nil, nil, nil, { "data-action": "change->checked#toggleAll", "data-checked-target": "all" } = t(".select_all") %td %em= distributor.name @@ -36,7 +36,7 @@ distributor_shipping_method.id, @order_cycle.distributor_shipping_methods.include?(distributor_shipping_method), id: "order_cycle_selected_distributor_shipping_method_ids_#{distributor_shipping_method.id}", - data: ({ "action" => "change->select-all#toggleCheckbox", "select-all-target" => "checkbox" } if distributor_shipping_method.shipping_method.frontend?) + data: ({ "action" => "change->checked#toggleCheckbox", "checked-target" => "checkbox" } if distributor_shipping_method.shipping_method.frontend?) = distributor_shipping_method.shipping_method.name - distributor.shipping_methods.backend.each do |shipping_method| %label.disabled @@ -52,11 +52,11 @@ = hidden_field_tag "order_cycle[selected_distributor_payment_method_ids][]", "" - @order_cycle.distributors.each do |distributor| - distributor_payment_methods = @order_cycle.attachable_distributor_payment_methods.where("distributor_id = ?", distributor.id).includes(:payment_method) - %tr{ class: "distributor-#{distributor.id}-payment-methods", "data-controller": "select-all" } + %tr{ class: "distributor-#{distributor.id}-payment-methods", "data-controller": "checked" } %td.text-center - if distributor_payment_methods.many? %label - = check_box_tag nil, nil, nil, { "data-action": "change->select-all#toggleAll", "data-select-all-target": "all" } + = check_box_tag nil, nil, nil, { "data-action": "change->checked#toggleAll", "data-checked-target": "all" } = t(".select_all") %td %em= distributor.name @@ -67,7 +67,7 @@ distributor_payment_method.id, @order_cycle.distributor_payment_methods.include?(distributor_payment_method), id: "order_cycle_selected_distributor_payment_method_ids_#{distributor_payment_method.id}", - data: ({ "action" => "change->select-all#toggleCheckbox", "select-all-target" => "checkbox" } if distributor_payment_method.payment_method.frontend?) + data: ({ "action" => "change->checked#toggleCheckbox", "checked-target" => "checkbox" } if distributor_payment_method.payment_method.frontend?) = distributor_payment_method.payment_method.name - distributor.payment_methods.inactive_or_backend.each do |payment_method| %label.disabled diff --git a/app/views/admin/order_cycles/edit.html.haml b/app/views/admin/order_cycles/edit.html.haml index 56151db299..3dcc757370 100644 --- a/app/views/admin/order_cycles/edit.html.haml +++ b/app/views/admin/order_cycles/edit.html.haml @@ -5,7 +5,8 @@ - mails_sent = @order_cycle.mails_sent? - url = main_app.notify_producers_admin_order_cycle_path - confirm_msg = "#{t('.notify_producers_tip')} #{t(:are_you_sure)}" - %a.button.icon-email.with-tip{ href: url, data: { method: 'post', confirm: confirm_msg }, 'data-powertip': t('.notify_producers_tip') } + + %a.button.icon-email.with-tip{ href: url, data: { method: :post, "ujs-navigate": "false", confirm: confirm_msg }, 'data-powertip': t('.notify_producers_tip') } = mails_sent ? t('.re_notify_producers') : t(:notify_producers) - if mails_sent .badge.icon-ok.success diff --git a/app/views/admin/shared/_flashes.html.haml b/app/views/admin/shared/_flashes.html.haml new file mode 100644 index 0000000000..57673b3f48 --- /dev/null +++ b/app/views/admin/shared/_flashes.html.haml @@ -0,0 +1,6 @@ +#flashes + - if defined? flashes + - flashes.each do |type, msg| + .animate-show{"data-controller": "flash"} + .flash{type: "#{type}", class: "#{type}"} + %span= msg diff --git a/app/views/admin/shared/_stimulus_page_controls.html.haml b/app/views/admin/shared/_stimulus_page_controls.html.haml new file mode 100644 index 0000000000..9e69c82203 --- /dev/null +++ b/app/views/admin/shared/_stimulus_page_controls.html.haml @@ -0,0 +1,8 @@ += select_tag :per_page, + options_for_select([15, 50, 100].collect{|num| [t('js.admin.orders.index.per_page', results: num), num] }, params[:per_page]), + { class: "no-search primary per-page-dropdown", data: { controller: "tom-select search", action: "change->search#changePerPage" } } + +- if pagy + %span.per-page-feedback + = t("spree.admin.orders.index.results_found", number: pagy.count) + = t("spree.admin.orders.index.viewing", start: pagy.from, end: pagy.to ) diff --git a/app/views/admin/shared/_stimulus_pagination.html.haml b/app/views/admin/shared/_stimulus_pagination.html.haml new file mode 100644 index 0000000000..e7e97fc643 --- /dev/null +++ b/app/views/admin/shared/_stimulus_pagination.html.haml @@ -0,0 +1,22 @@ +- link = pagy_link_proc(pagy) + +.pagination{ "data-controller": "search" } + - if pagy.prev + %button{ data: { action: 'click->search#changePage', page: pagy.prev } }!= pagy_t('pagy.nav.prev') + - else + %button.disabled{disabled: "disabled"}!= pagy_t('pagy.nav.prev') + + - pagy.series.each do |item| # series example: [1, :gap, 7, 8, "9", 10, 11, :gap, 36] + - if item.is_a?(Integer) # page link + %button{ data: { action: 'click->search#changePage', page: item } }= item + + - elsif item.is_a?(String) # current page + %button.active= item + + - elsif item == :gap # page gap + %span.pagination-ellipsis!= pagy_t('pagy.nav.gap') + + - if pagy.next + %button{ data: { action: 'click->search#changePage', page: pagy.next } }!= pagy_t('pagy.nav.next') + - else + %button.disabled.pagination-next{disabled: "disabled"}!= pagy_t('pagy.nav.next') diff --git a/app/views/admin/shared/_tooltip.html.haml b/app/views/admin/shared/_tooltip.html.haml index 3d0f140518..0f193e60b9 100644 --- a/app/views/admin/shared/_tooltip.html.haml +++ b/app/views/admin/shared/_tooltip.html.haml @@ -1,5 +1,6 @@ %div{"data-controller": "tooltip"} - %a{"data-tooltip-target": "element", "data-action": "mouseenter->tooltip#showTooltip mouseleave->tooltip#hideTooltip"}= t('admin.whats_this') + %a{"data-tooltip-target": "element"} + = t('admin.whats_this') .tooltip-container .tooltip{"data-tooltip-target": "tooltip"} = sanitize tooltip_text diff --git a/app/views/admin/subscriptions/_autocomplete.html.haml b/app/views/admin/subscriptions/_autocomplete.html.haml index 789f27104c..784c77009e 100644 --- a/app/views/admin/subscriptions/_autocomplete.html.haml +++ b/app/views/admin/subscriptions/_autocomplete.html.haml @@ -16,5 +16,5 @@ %input#add_quantity.fullwidth{ type: 'number', min: 1, ng: { model: 'newItem.quantity' } } %td .actions - %a.icon-plus.button.fullwidth{ href: 'javascript:void(0)', method: :post, ng: { click: 'addSubscriptionLineItem()' } } + %a.icon-plus.button.fullwidth{ href: 'javascript:void(0)', ng: { click: 'addSubscriptionLineItem()' } } = t('.add') diff --git a/app/views/admin/terms_of_service_files/show.html.haml b/app/views/admin/terms_of_service_files/show.html.haml index 68373724a0..2f3c5b387b 100644 --- a/app/views/admin/terms_of_service_files/show.html.haml +++ b/app/views/admin/terms_of_service_files/show.html.haml @@ -7,7 +7,7 @@ .admin-current-terms-of-service - if @current_file %p= t(".current_terms_html", tos_link: link_to(t(".terms_of_service"), @current_file.attachment), datetime: @current_file.updated_at) - %p= link_to t(".delete"), main_app.admin_terms_of_service_files_path, method: "delete", data: { confirm: t(".confirm_delete") } + %p= link_to t(".delete"), main_app.admin_terms_of_service_files_path, data: { method: :delete, "ujs-navigate": "false", confirm: t(".confirm_delete") } - else %p = t(".no_files") diff --git a/app/views/spree/admin/mail_methods/edit.html.haml b/app/views/spree/admin/mail_methods/edit.html.haml index 9e79403270..5a03702c21 100644 --- a/app/views/spree/admin/mail_methods/edit.html.haml +++ b/app/views/spree/admin/mail_methods/edit.html.haml @@ -5,7 +5,8 @@ - content_for :page_actions do %li - = link_to_with_icon 'icon-envelope-alt', t("spree.admin.mail_methods.send_testmail"), testmail_admin_mail_methods_path, method: :post, title: t("spree.admin.mail_methods.send_testmail"), class: 'send_mail button no-text' + = link_to_with_icon 'icon-envelope-alt', t("spree.admin.mail_methods.send_testmail"), testmail_admin_mail_methods_path, + data: { method: :post, "ujs-navigate": "false" }, title: t("spree.admin.mail_methods.send_testmail"), class: 'send_mail button no-text' = render partial: 'spree/shared/error_messages', locals: { target: @mail_method } diff --git a/app/views/spree/admin/orders/_bulk_actions.html.haml b/app/views/spree/admin/orders/_bulk_actions.html.haml new file mode 100644 index 0000000000..7351399aa7 --- /dev/null +++ b/app/views/spree/admin/orders/_bulk_actions.html.haml @@ -0,0 +1,25 @@ +.ofn-drop-down-with-prepend + .ofn-drop-down-prepend.disabled{ "data-checked-target": "disable" } + %span{ "data-controller": "checked-feedback", "data-checked-feedback-translation-value": "spree.admin.orders.index.selected" } + = t("spree.admin.orders.index.selected", count: 0) + + %button.plain.ofn-drop-down.disabled{ "data-checked-target": "disable" } + %span{ class: 'icon-reorder' } + ="#{t('admin.actions')}".html_safe + %span.toggle-off.icon-caret-up + %span.toggle-on.icon-caret-down + + %div.menu.dropdown-content + %div.menu_item + %span.name{ "data-controller": "modal-link", "data-action": "click->modal-link#open", "data-modal-link-target-value": "resend_confirmation" } + = t('spree.admin.orders.index.resend_confirmation') + - if Spree::Config[:enable_invoices?] + %div.menu_item + %span.name{ "data-controller": "modal-link", "data-action": "click->modal-link#open", "data-modal-link-target-value": "send_invoice" } + = t('spree.admin.orders.index.send_invoice') + %div.menu_item + %span.name{ "data-controller": "bulk-actions", "data-action": "click->bulk-actions#perform", "data-bulk-actions-reflex-value": "Admin::Orders#bulk_invoice" } + = t('spree.admin.orders.index.print_invoices') + %div.menu_item + %span.name{ "data-controller": "modal-link", "data-action": "click->modal-link#open", "data-modal-link-target-value": "cancel_orders" } + = t('spree.admin.orders.index.cancel_orders') diff --git a/app/views/spree/admin/orders/_filters.html.haml b/app/views/spree/admin/orders/_filters.html.haml index f328c149ea..fcf14a4441 100644 --- a/app/views/spree/admin/orders/_filters.html.haml +++ b/app/views/spree/admin/orders/_filters.html.haml @@ -1,59 +1,61 @@ -%div.admin-orders-index-search - = form_tag spree.admin_orders_url, {name: "orders_form", "ng-submit" => "fetchResults()"} do +%div.admin-orders-index-search{ "data-controller": "search", "data-search-restore-value": @stored_query } + = form_with url: spree.admin_orders_url, id: "orders_form", method: :get, data: { remote: true, "search-target": "form" } do + = hidden_field_tag :page, 1, class: "page" + = hidden_field_tag :per_page, 15, class: "per-page" + = hidden_field_tag "[q][s]", params.dig(:q, :s) || "completed_at desc", class: "sort", "data-default": "completed_at desc" + .field-block.alpha.four.columns .date-range-filter.field = label_tag nil, t(:date_range) - .date-range-fields{ data: { controller: "flatpickr", "flatpickr-mode-value": "range", "flatpickr-default-date": "{{ [q.completed_at_gteq, q.completed_at_lteq] }}" } } + .date-range-fields{ data: { controller: "flatpickr", "flatpickr-mode-value": "range" } } = text_field_tag nil, nil, class: "datepicker", data: { "flatpickr-target": "instance", action: "flatpickr_clear@window->flatpickr#clear" } = text_field_tag "q[completed_at_gteq]", nil, "ng-model": "q.completed_at_gteq", data: { "flatpickr-target": "start" }, style: "display: none" = text_field_tag "q[completed_at_lteq]", nil, "ng-model": "q.completed_at_lteq", data: { "flatpickr-target": "end" }, style: "display: none" .field = label_tag nil, t(:status) - %select2-watch-ng-model{'ng-model': 'q.state_eq'} - = select_tag("q[state_eq]", - options_for_select(Spree::Order.state_machines[:state].states.collect {|s| [t("spree.order_state.#{s.name}"), s.value]}), - {include_blank: true, class: 'select2', 'ng-model' => 'q.state_eq'}) + = select_tag("q[state_eq]", + options_for_select(Spree::Order.state_machines[:state].states.collect {|s| [t("spree.order_state.#{s.name}"), s.value]}), + { include_blank: true, class: "primary", "data-controller": "tom-select" }) .four.columns .field = label_tag "q_number_cont", t(:order_number) - = text_field_tag "q[number_cont]", nil, "ng-model" => "q.number_cont", "ng-keypress" => "$event.keyCode === 13 && fetchResults()" + = text_field_tag "q[number_cont]", nil .field = label_tag "q_email_cont", t(:email) - = email_field_tag "q[email_cont]", nil, "ng-model" => "q.email_cont", "ng-keypress" => "$event.keyCode === 13 && fetchResults()" + = email_field_tag "q[email_cont]", nil .four.columns .field = label_tag "q_bill_address_firstname_start", t(:first_name_begins_with) - = text_field_tag "q[bill_address_firstname_start]", nil, size: 25, "ng-model" => "q.bill_address_firstname_start", "ng-keypress" => "$event.keyCode === 13 && fetchResults()" + = text_field_tag "q[bill_address_firstname_start]", nil, size: 25 .field = label_tag "q_bill_address_lastname_start", t(:last_name_begins_with) - = text_field_tag "q[bill_address_lastname_start]", nil, size: 25, "ng-model" => "q.bill_address_lastname_start", "ng-keypress" => "$event.keyCode === 13 && fetchResults()" + = text_field_tag "q[bill_address_lastname_start]", nil, size: 25 .omega.four.columns - .field.checkbox + .field.checkbox.inline-checkbox %label - = check_box_tag "q[completed_at_not_null]", 1, true, {'ng-model' => 'q.completed_at_not_null'} + = check_box_tag "q[completed_at_not_null]", 1, true = t(:show_only_complete_orders) .field = label_tag nil, t(:shipping_method) - %select2-watch-ng-model{'ng-model': 'q.shipping_method_id'} - = select_tag("q[shipping_method_id]", - options_for_select(Spree::ShippingMethod.managed_by(spree_current_user).collect {|s| [t("spree.shipping_method_names.#{s.name}"), s.id]}), - {include_blank: true, class: 'select2', 'ng-model': 'q.shipping_method_id'}) + = select_tag(:shipping_method_id, + options_for_select(Spree::ShippingMethod.managed_by(spree_current_user).collect {|s| [t("spree.shipping_method_names.#{s.name}"), s.id]}), + { include_blank: true, class: "primary", "data-controller": "tom-select" }) .field-block.alpha.eight.columns = label_tag nil, t(:distributors) - %select2-watch-ng-model{'ng-model': 'q.distributor_id_in'} - = select_tag("q[distributor_id_in]", - options_for_select(Enterprise.is_distributor.managed_by(spree_current_user).map {|e| [e.name, e.id]}, params[:distributor_ids]), - {class: "select2 fullwidth", multiple: true, 'ng-model' => 'q.distributor_id_in'}) + = select_tag("q[distributor_id_in]", + options_for_select(Enterprise.is_distributor.managed_by(spree_current_user).map {|e| [e.name, e.id]}, params[:distributor_ids]), + { class: "fullwidth", multiple: true, data: { controller: "tom-select", "tom-select-options-value": { plugins: ['remove_button'], maxItems: nil } }}) .field-block.omega.eight.columns = label_tag nil, t(:order_cycles) - %select2-watch-ng-model{'ng-model': 'q.order_cycle_id_in'} - = select_tag("q[order_cycle_id_in]", - options_for_select(OrderCycle.managed_by(spree_current_user).where('order_cycles.orders_close_at is not null').order('order_cycles.orders_close_at DESC').map {|oc| [oc.name, oc.id]}, params[:order_cycle_ids]), - {class: "select2 fullwidth", multiple: true, 'ng-model' => 'q.order_cycle_id_in'}) + = select_tag("q[order_cycle_id_in]", + options_for_select(OrderCycle.managed_by(spree_current_user).where('order_cycles.orders_close_at is not null').order('order_cycles.orders_close_at DESC').map {|oc| [oc.name, oc.id]}, params[:order_cycle_ids]), + { class: "fullwidth", multiple: true, data: { controller: "tom-select", "tom-select-options-value": { plugins: ['remove_button'], maxItems: nil } }}) .clearfix - .actions.filter-actions - %a.button.icon-search{'ng-click' => 'fetchResults()'} - = t(:filter_results) - %a.button{'ng-click' => 'clearFilters()', "id": "clear_filters_button"} - = t(:clear_filters) - + .actions.filter-actions{ style: "column-gap: 0" } + .eight.columns.alpha + %button.float-right.mr-0{type: "submit", class: "button"} + %i.icon-search + = t(:filter_results) + .eight.columns.omega + %button.float-left{"id": "clear_filters_button", type: "button", "data-controller": "search", "data-action": "click->search#reset" } + = t(:clear_filters) diff --git a/app/views/spree/admin/orders/_table.html.haml b/app/views/spree/admin/orders/_table.html.haml new file mode 100644 index 0000000000..f15cc261d1 --- /dev/null +++ b/app/views/spree/admin/orders/_table.html.haml @@ -0,0 +1,30 @@ +.row.index-controls + %div{ style: "display: flex; justify-content: space-between;" } + = render partial: "bulk_actions" + .per-page.right + = render partial: 'admin/shared/stimulus_page_controls', locals: { pagy: pagy } + +%table#listing_orders.index.responsive{width: "100%" } + %colgroup + %col{style: "width: 3%"} + %thead + %tr + %th + %input#selectAll{ type: 'checkbox', data: { "checked-target": "all", action: "change->checked#toggleAll" } } + %th + = t(:products_distributor) + + - columns = ['completed_at', 'number', 'state', 'payment_state', 'shipment_state', 'email', 'bill_address_lastname', 'total'] + + = render partial: "spree/admin/shared/stimulus_sortable_header", collection: columns, as: :column, + locals: { sorted: params.dig(:q, :s), default: "completed_at desc" } + + %th.actions + %tbody + = render partial: "table_row", collection: orders, as: :order + + +- if pagy&.count&.positive? + = render partial: "admin/shared/stimulus_pagination", locals: { pagy: pagy } +- else + .no-objects-found= t('spree.admin.orders.index.no_orders_found') diff --git a/app/views/spree/admin/orders/_table_row.html.haml b/app/views/spree/admin/orders/_table_row.html.haml new file mode 100644 index 0000000000..42357d161e --- /dev/null +++ b/app/views/spree/admin/orders/_table_row.html.haml @@ -0,0 +1,53 @@ +%tr{ id: dom_id(order), class: "state-#{order.state}" } + %td.align-center + %input{type: 'checkbox', value: order.id, name: 'bulk_ids[]', "data-checked-target": "checkbox", "data-action": "change->checked#toggleCheckbox" } + %td.align-center + = order.distributor.name + %td.align-center + = I18n.l(order.completed_at, format: '%B %d, %Y') if order.completed_at + %td + %a{ href: edit_admin_order_path(order) } + = order.number + - if order.special_instructions.present? + %div + %br + %div{ "data-controller": "tooltip", "data-tooltip-tip-value": order.special_instructions.to_s } + %span.icon-warning-sign{ "data-tooltip-target": "element" } + = t('spree.admin.orders.index.note') + %td.align-center + %span.state{ class: order.state.to_s } + = t('js.admin.orders.order_state.' + order.state.to_s) + %td.align-center + - if order.payment_state + %span.state{class: 'order.payment_state'} + %a{href: spree.admin_order_payments_path(order) } + = t('js.admin.orders.payment_states.' + order.payment_state.to_s) + - if order.display_outstanding_balance + %span + = "(#{order.display_outstanding_balance})" + %td.align-center + - if order.shipment_state + %span.state{class: order.shipment_state.to_s} + = t('js.admin.orders.shipment_states.' + order.shipment_state.to_s) + %td + %a{ href: "mailto:#{order.email}", target: "_blank" } + = order.email + %td + = order.bill_address.full_name + %td.align-center + %span + = order.display_total + %td.actions + %div.row-loading-icons + - if local_assigns[:success] + %i.success.icon-ok-sign{"data-controller": "ephemeral"} + %a.icon_link.with-tip.icon-edit.no-text{href: edit_admin_order_path(order), 'ofn-with-tip' => t('spree.admin.orders.index.edit')} + - if order.ready_to_ship? + %div{ "data-controller": "tooltip", "data-tooltip-tip-value": t('spree.admin.orders.index.ship') } + %button.icon-road.icon_link.with-tip.no-text{"data-reflex": "click->Admin::OrdersReflex#ship", "data-id": order.id.to_s, + "data-tooltip-target": "element" } + + - if order.payment_required? && order.pending_payments.reject(&:requires_authorization?).any? + %div{ "data-controller": "tooltip", "data-tooltip-tip-value": t('spree.admin.orders.index.capture') } + %button.icon-capture.icon_link.no-text{"data-reflex": "click->Admin::OrdersReflex#capture", "data-id": order.id.to_s, + "data-tooltip-target": "element" } diff --git a/app/views/spree/admin/orders/bulk/_invoice_link.html.haml b/app/views/spree/admin/orders/bulk/_invoice_link.html.haml new file mode 100644 index 0000000000..dbc5c455d5 --- /dev/null +++ b/app/views/spree/admin/orders/bulk/_invoice_link.html.haml @@ -0,0 +1,7 @@ +%p.message + = t('js.admin.orders.index.bulk_invoice_created') + +%br + +%a.button.primary{ target: '_blank', href: invoice_url } + = t('js.admin.orders.index.view_file') diff --git a/app/views/spree/admin/orders/bulk/_invoice_modal.html.haml b/app/views/spree/admin/orders/bulk/_invoice_modal.html.haml new file mode 100644 index 0000000000..07c2f30121 --- /dev/null +++ b/app/views/spree/admin/orders/bulk/_invoice_modal.html.haml @@ -0,0 +1,15 @@ +%div{ id: "bulk_invoices_modal", "data-controller": "modal", "data-modal-instant-value": true, "data-action": "keyup@document->modal#closeIfEscapeKey" } + .reveal-modal-bg.fade{ "data-modal-target": "background", "data-action": "click->modal#remove" } + .reveal-modal.fade.tiny.help-modal{ "data-modal-target": "modal" } + %div.fullwidth.align-center + %h4.modal-title + = t('js.admin.orders.index.compiling_invoices') + %br + %br + .modal-content + .modal-loading + %img.spinner{ src: image_path("/spinning-circles.svg") } + %br + %br + %p= t('js.admin.orders.index.please_wait') + %br diff --git a/app/views/spree/admin/orders/edit.html.haml b/app/views/spree/admin/orders/edit.html.haml index 1049a0849f..b8556d861a 100644 --- a/app/views/spree/admin/orders/edit.html.haml +++ b/app/views/spree/admin/orders/edit.html.haml @@ -8,8 +8,8 @@ %li= event_links = render partial: 'spree/admin/shared/order_links' - if can?(:admin, Spree::Order) - %li{"ng-controller" => "ordersCtrl"} - %a.button.icon-arrow-left{icon: 'icon-arrow-left', ng: { href: admin_orders_path }} + %li + %a.button.icon-arrow-left{icon: 'icon-arrow-left', href: admin_orders_path } = t(:back_to_orders_list) = render partial: "spree/admin/shared/order_page_title" diff --git a/app/views/spree/admin/orders/index.html.haml b/app/views/spree/admin/orders/index.html.haml index 33224c8957..26a7965a69 100644 --- a/app/views/spree/admin/orders/index.html.haml +++ b/app/views/spree/admin/orders/index.html.haml @@ -1,137 +1,33 @@ - content_for :page_title do = t('.listing_orders') +- content_for :minimal_js, true + - content_for :page_actions do %li = button_link_to t('.new_order'), spree.new_admin_order_url, icon: 'icon-plus', id: 'admin_new_order' = render partial: 'spree/admin/shared/order_sub_menu' -- content_for :main_ng_app_name do - = "ofn.admin" - -- content_for :main_ng_ctrl_name do - = "ordersCtrl" - - content_for :table_filter_title do = t(:search) - content_for :table_filter do = render partial: 'filters' -.row.index-controls{'ng-show' => '!RequestMonitor.loading && orders.length > 0'} - %div{style: "display: flex; justify-content: space-between;"} - .ofn-drop-down-with-prepend - .ofn-drop-down-prepend{"ng-class": "selected_orders.length == 0 ? 'disabled' : ''"} - {{ "spree.admin.orders.index.selected" | t:{count: selected_orders.length} }} - .ofn-drop-down{"ng-class": "selected_orders.length == 0 ? 'disabled' : ''"} - %span{ :class => 'icon-reorder' } - ="#{t('admin.actions')}".html_safe - %span{ 'ng-class' => "expanded && 'icon-caret-up' || !expanded && 'icon-caret-down'" } - %div.menu{ 'ng-show' => "expanded" } - %div.menu_item - %span.name{ "data-controller": "modal-link", "data-action": "click->modal-link#open", "data-modal-link-target-value": "resend_confirmation" } - = t('.resend_confirmation') - - if Spree::Config[:enable_invoices?] - %div.menu_item - %span.name{ "data-controller": "modal-link", "data-action": "click->modal-link#open", "data-modal-link-target-value": "send_invoice" } - = t('.send_invoice') - %div.menu_item - %span.name.invoices-modal{'ng-controller' => 'bulkInvoiceCtrl', 'ng-click' => 'createBulkInvoice()' } - = t('.print_invoices') - %div.menu_item - %span.name{ "data-controller": "modal-link", "data-action": "click->modal-link#open", "data-modal-link-target-value": "cancel_orders" } - = t('.cancel_orders') - - = render partial: 'admin/shared/angular_per_page_controls', locals: { position: "right", model: "orders" } - -%table#listing_orders.index.responsive{width: "100%", 'ng-init' => 'initialise()', 'ng-show' => "!RequestMonitor.loading && orders.length > 0" } - %colgroup - %col{style: "width: 3%"} - %thead - %tr - %th - %input#selectAll{type: 'checkbox', 'ng-change' => 'toggleAll()', 'ng-model' => 'select_all'} - %th - = t(:products_distributor) - %th - %a{'ng-click' => "sortOptions.toggle('completed_at')"} - = t(:completed_at, scope: 'activerecord.attributes.spree/order') - %span{'ng-show' => "sorting == 'completed_at asc'"}= "▲".html_safe - %span{'ng-show' => "sorting == 'completed_at desc' || sorting === undefined"}= "▼".html_safe - - - ['number', 'state', 'payment_state', 'shipment_state', 'email', 'bill_address_lastname', 'total'].each do |column_name| - %th - = render partial: 'spree/admin/shared/sortable_header', locals: {column_name: column_name} - - %th.actions - %tbody - %tr{ng: {repeat: 'order in orders track by order.id', class: {even: "'even'", odd: "'odd'"}}, 'ng-class' => "{'state-{{order.state}}': true, 'row-loading': rowStatus[order.id] == 'loading'}"} - %td.align-center - %input{type: 'checkbox', 'ng-model' => 'checkboxes[order.id]', 'ng-change' => 'toggleSelection(order.id)', value: '{{order.id}}', name: 'order_ids[]'} - %td.align-center - {{order.distributor_name}} - %td.align-center - {{order.completed_at}} - %td - %a{'ng-href' => '{{order.edit_path}}'} - {{order.number}} - %div{'ng-if' => 'order.special_instructions'} - %br - %span.icon-warning-sign{'ofn-with-tip' => "{{order.special_instructions}}"} - = t('.note') - %td.align-center - %span.state{'ng-class' => 'order.state'} - {{'js.admin.orders.order_state.' + order.state | t}} - %td.align-center - %span.state{'ng-class' => 'order.payment_state', 'ng-if' => 'order.payment_state'} - %a{'ng-href' => '{{order.payments_path}}' } - {{'js.admin.orders.payment_states.' + order.payment_state | t}} - %span{'ng-if' => 'order.display_outstanding_balance'} - ({{order.display_outstanding_balance}}) - %td.align-center - %span.state{'ng-class' => 'order.shipment_state', 'ng-if' => 'order.shipment_state'} - {{'js.admin.orders.shipment_states.' + order.shipment_state | t}} - %td - %a{ ng: { href: "mailto:{{order.email}}" } } - {{order.email}} - %td - {{order.full_name}} - %td.align-center - %span{'ng-bind-html' => 'order.display_total'} - %td.actions - %div.row-loading-icons - %div{ng: {show: 'rowStatus[order.id] == "loading"', cloak: true}, style: "width: 30px; height: 30px;"} - = render partial: "components/spinner" - %i.success.icon-ok-sign{ng: {show: 'rowStatus[order.id] == "success"'} } - %i.error.icon-remove-sign.with-tip{ng: {show: 'rowStatus[order.id] == "error"'}, 'ofn-with-tip' => t('.order_not_updated')} - %a.icon_link.with-tip.icon-edit.no-text{'ng-href' => '{{order.edit_path}}', 'data-action' => 'edit', 'ofn-with-tip' => t('.edit')} - %div{'ng-if' => 'order.ready_to_ship'} - %button.icon-road.icon_link.with-tip.no-text{'ng-click' => 'shipOrder(order)', rel: 'nofollow', 'ofn-with-tip' => t('.ship')} - %div{'ng-if' => 'order.ready_to_capture'} - %button.icon-capture.icon_link.no-text{'ng-click' => 'capturePayment(order)', rel: 'nofollow', 'ofn-with-tip' => t('.capture')} - -.sixteen.columns.alpha#loading{ 'ng-show' => 'RequestMonitor.loading' } - = render partial: "components/admin_spinner" - %h1 - = t('.loading') - -%div{'ng-show' => "!RequestMonitor.loading && orders.length > 0" } - = render partial: 'admin/shared/angular_pagination' - -.no-objects-found{'ng-show' => "!RequestMonitor.loading && orders.length == 0"} - = t('.no_orders_found') +#orders-index{"data-controller": "search checked"} + = render partial: "table", locals: { pagy: @pagy, orders: @orders } = render 'spree/admin/shared/custom-confirm' -= render ConfirmModalComponent.new(id: "resend_confirmation", confirm_actions: "click->resend-confirmation-email#confirm", controllers: "resend-confirmation-email") do += render ConfirmModalComponent.new(id: "resend_confirmation", confirm_actions: "click->bulk-actions#perform", controller: "bulk-actions", reflex: "Admin::Orders#resend_confirmation_emails") do .margin-bottom-30 = t('.resend_confirmation_confirm_html') -= render ConfirmModalComponent.new(id: "send_invoice", confirm_actions: "click->send-invoice#confirm", controllers: "send-invoice") do += render ConfirmModalComponent.new(id: "send_invoice", confirm_actions: "click->bulk-actions#perform", controller: "bulk-actions", reflex: "Admin::Orders#send_invoices") do .margin-bottom-30 = t('.send_invoice_confirm_html') -= render ConfirmModalComponent.new(id: "cancel_orders", confirm_actions: "click->cancel-orders#confirm", controllers: "cancel-orders", message: "spree/admin/orders/messages/cancel_orders") do += render ConfirmModalComponent.new(id: "cancel_orders", confirm_actions: "click->bulk-actions#perform", controller: "bulk-actions", reflex: "Admin::Orders#cancel_orders", message: "spree/admin/orders/messages/cancel_orders") do .margin-bottom-30 = t("js.admin.orders.cancel_the_order_html") diff --git a/app/views/spree/admin/orders/messages/_cancel_orders.html.haml b/app/views/spree/admin/orders/messages/_cancel_orders.html.haml index 00d30d1eed..9b689ff75e 100644 --- a/app/views/spree/admin/orders/messages/_cancel_orders.html.haml +++ b/app/views/spree/admin/orders/messages/_cancel_orders.html.haml @@ -1,10 +1,10 @@ .modal-message - .form + %form{ "data-bulk-actions-target": "extraParams" } %input{ type: "checkbox", name: "send_cancellation_email", value: "1", id: "send_cancellation_email", checked: "true" } %label{ for: "send_cancellation_email" } = t("js.admin.orders.cancel_the_order_send_cancelation_email") %br - %input{ type: "checkbox", name: "restock_items", id: "restock_items", checked: "true" } + %input{ type: "checkbox", name: "restock_items", value: "1", id: "restock_items", checked: "true" } %label{ for: "restock_items" } = t("js.admin.orders.restock_items") .margin-bottom-30 diff --git a/app/views/spree/admin/payments/_list.html.haml b/app/views/spree/admin/payments/_list.html.haml index 6daa450eca..4e1a1ec066 100644 --- a/app/views/spree/admin/payments/_list.html.haml +++ b/app/views/spree/admin/payments/_list.html.haml @@ -16,4 +16,5 @@ %span{class: "state #{payment.state}"}= t(payment.state, scope: "spree.payment_states", default: payment.state.capitalize) %td.actions - payment.actions.each do |action| - = link_to_with_icon "icon-#{action}", Spree.t(action), fire_admin_order_payment_path(@order, payment, e: action), method: :put, no_text: true, data: {action: action, disable_with: ""} + = link_to_with_icon "icon-#{action}", Spree.t(action), fire_admin_order_payment_path(@order, payment, e: action), + no_text: true, data: { method: :put, "ujs-navigate": "false", action: action, disable_with: "" } diff --git a/app/views/spree/admin/return_authorizations/edit.html.haml b/app/views/spree/admin/return_authorizations/edit.html.haml index 71c32c0ab3..190e6e31c5 100644 --- a/app/views/spree/admin/return_authorizations/edit.html.haml +++ b/app/views/spree/admin/return_authorizations/edit.html.haml @@ -1,10 +1,12 @@ - content_for :page_actions do %li - if @return_authorization.can_receive? - = button_link_to t('.receive'), fire_admin_order_return_authorization_url(@order, @return_authorization, e: 'receive'), method: :put, data: { confirm: t('.are_you_sure') }, icon: 'icon-download-alt' + = button_link_to t('.receive'), fire_admin_order_return_authorization_url(@order, @return_authorization, e: 'receive'), + data: { method: :put, "ujs-navigate": "false", confirm: t('.are_you_sure') }, icon: 'icon-download-alt' %li - if @return_authorization.can_cancel? - = button_link_to t('actions.cancel'), fire_admin_order_return_authorization_url(@order, @return_authorization, e: 'cancel'), method: :put, data: { confirm: t('.are_you_sure') }, icon: 'icon-remove' + = button_link_to t('actions.cancel'), fire_admin_order_return_authorization_url(@order, @return_authorization, e: 'cancel'), + data: { method: :put, "ujs-navigate": "false", confirm: t('.are_you_sure') }, icon: 'icon-remove' = render partial: 'spree/admin/shared/order_page_title' = render partial: 'spree/admin/shared/order_tabs', locals: { current: 'Return Authorizations' } diff --git a/app/views/spree/admin/shared/_head.html.haml b/app/views/spree/admin/shared/_head.html.haml index d0fe96ce4a..97336242ce 100644 --- a/app/views/spree/admin/shared/_head.html.haml +++ b/app/views/spree/admin/shared/_head.html.haml @@ -3,8 +3,6 @@ = csrf_meta_tags = action_cable_meta_tag -= action_cable_meta_tag - %title - if content_for? :html_title = yield :html_title @@ -20,7 +18,11 @@ = stylesheet_pack_tag 'admin-styles', media: "screen, print" = render "layouts/bugsnag_js" -= javascript_include_tag 'admin/all' + +- if content_for? :minimal_js + = javascript_include_tag 'admin_minimal' +- else + = javascript_include_tag 'admin/all' = render "spree/admin/shared/translations" = render "spree/admin/shared/routes" diff --git a/app/views/spree/admin/shared/_stimulus_sortable_header.html.haml b/app/views/spree/admin/shared/_stimulus_sortable_header.html.haml new file mode 100644 index 0000000000..46443016ce --- /dev/null +++ b/app/views/spree/admin/shared/_stimulus_sortable_header.html.haml @@ -0,0 +1,8 @@ +%th + %a{ "data-action": "click->search#changeSorting", "data-column": "#{column}", "data-current": sorted.to_s } + = t("spree.admin.shared.sortable_header.#{column.to_s}") + + - if sorted == "#{column} asc" || sorted.blank? && local_assigns[:default] == "#{column} asc" + = "▲".html_safe + - if sorted == "#{column} desc" || sorted.blank? && local_assigns[:default] == "#{column} desc" + = "▼".html_safe diff --git a/app/views/spree/admin/shared/_tabs.html.haml b/app/views/spree/admin/shared/_tabs.html.haml index 91efb77da3..d84e381c57 100644 --- a/app/views/spree/admin/shared/_tabs.html.haml +++ b/app/views/spree/admin/shared/_tabs.html.haml @@ -1,7 +1,7 @@ = tab :overview, label: 'dashboard', url: spree.admin_dashboard_path, icon: 'icon-dashboard' = tab :products, :properties, :inventory, :product_import, :images, :variants, :product_properties, :group_buy_options, :seo, url: admin_products_path, icon: 'icon-th-large' = tab :order_cycles, url: main_app.admin_order_cycles_path, icon: 'icon-refresh' -= tab :orders, :subscriptions, :customer_details, :adjustments, :payments, :return_authorizations, url: admin_orders_path('q[s]' => 'completed_at desc'), icon: 'icon-shopping-cart' += tab :orders, :subscriptions, :customer_details, :adjustments, :payments, :return_authorizations, url: admin_orders_path, icon: 'icon-shopping-cart' = tab :reports, url: main_app.admin_reports_path, icon: 'icon-file' = tab :general_settings, :mail_methods, :tax_categories, :tax_rates, :tax_settings, :zones, :countries, :states, :payment_methods, :taxonomies, :shipping_methods, :shipping_categories, :enterprise_fees, :contents, :invoice_settings, :matomo_settings, :stripe_connect_settings, label: 'configuration', icon: 'icon-wrench', url: edit_admin_general_settings_path = tab :enterprises, :enterprise_relationships, :vouchers, :oidc_settings, url: main_app.admin_enterprises_path diff --git a/app/views/spree/admin/shared/_translations.html.erb b/app/views/spree/admin/shared/_translations.html.erb index 97eae43d00..96183fd864 100644 --- a/app/views/spree/admin/shared/_translations.html.erb +++ b/app/views/spree/admin/shared/_translations.html.erb @@ -1,4 +1,7 @@