diff --git a/Gemfile b/Gemfile index 49319ab065..388ab07feb 100644 --- a/Gemfile +++ b/Gemfile @@ -89,6 +89,8 @@ gem 'redis', '>= 4.0', require: ['redis', 'redis/connection/hiredis'] gem 'sidekiq' gem 'sidekiq-scheduler' +gem "cable_ready", "5.0.0.pre2" + gem 'combine_pdf' gem 'wicked_pdf' gem 'wkhtmltopdf-binary' diff --git a/Gemfile.lock b/Gemfile.lock index 7cb9b561a4..a807992f45 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -171,6 +171,9 @@ GEM activesupport (>= 3.0.0) uniform_notifier (~> 1.11) byebug (11.1.3) + cable_ready (5.0.0.pre2) + rails (>= 5.2) + thread-local (>= 1.1.0) cancancan (1.15.0) capybara (3.35.3) addressable @@ -622,6 +625,7 @@ GEM test-unit (3.4.7) power_assert thor (1.1.0) + thread-local (1.1.0) thwait (0.2.0) e2mmap tilt (2.0.10) @@ -698,6 +702,7 @@ DEPENDENCIES bugsnag bullet byebug + cable_ready (= 5.0.0.pre2) cancancan (~> 1.15.0) capybara catalog! diff --git a/app/assets/javascripts/darkswarm/all.js.coffee b/app/assets/javascripts/darkswarm/all.js.coffee index 9b0944cbd5..b425d57848 100644 --- a/app/assets/javascripts/darkswarm/all.js.coffee +++ b/app/assets/javascripts/darkswarm/all.js.coffee @@ -54,3 +54,23 @@ #= require_tree ./mixins #= require_tree ./directives #= require_tree . + +document.addEventListener "turbo:load", -> + window.injector = angular.bootstrap document.body, ["Darkswarm"] + true + +document.addEventListener "turbo:before-render", -> + if window.injector + rootscope = window.injector.get("$rootScope") + rootscope?.$destroy() + 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/darkswarm/directives/confirm_link_click.js.coffee b/app/assets/javascripts/darkswarm/directives/confirm_link_click.js.coffee deleted file mode 100644 index c4a861fda6..0000000000 --- a/app/assets/javascripts/darkswarm/directives/confirm_link_click.js.coffee +++ /dev/null @@ -1,9 +0,0 @@ -angular.module('Darkswarm').directive "confirmLinkClick", ($window) -> - restrict: 'A' - scope: - confirmMsg: '@confirmLinkClick' - link: (scope, elem, attr) -> - elem.bind 'click', (event) -> - unless confirm(scope.confirmMsg) - event.preventDefault() - event.stopPropagation() diff --git a/app/assets/stylesheets/darkswarm/animations.scss b/app/assets/stylesheets/darkswarm/animations.scss index d7fb952907..cd5f3a5f89 100644 --- a/app/assets/stylesheets/darkswarm/animations.scss +++ b/app/assets/stylesheets/darkswarm/animations.scss @@ -1,7 +1,21 @@ @import "mixins"; +.turbo-progress-bar { + background-color: $teal-400; +} + // ANIMATION FUNCTIONS +@keyframes fade-out-hide { + 0% {opacity: 1; visibility: visible;} + 99% {opacity: 0; visibility: visible;} + 100% {opacity: 0; visibility: hidden;} +} + +.animate-hide-500 { + animation: fade-out-hide 0.5s; +} + // @-webkit-keyframes slideInDown { 0% { diff --git a/app/controllers/concerns/cablecar_responses.rb b/app/controllers/concerns/cablecar_responses.rb new file mode 100644 index 0000000000..b98d158dae --- /dev/null +++ b/app/controllers/concerns/cablecar_responses.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +module CablecarResponses + extend ActiveSupport::Concern + + included do + include CableReady::Broadcaster + end + + private + + def partial(path, options = {}) + { html: render_to_string(partial: path, **options) } + end +end diff --git a/app/controllers/split_checkout_controller.rb b/app/controllers/split_checkout_controller.rb index 9849f10b19..63b2405aa4 100644 --- a/app/controllers/split_checkout_controller.rb +++ b/app/controllers/split_checkout_controller.rb @@ -8,6 +8,7 @@ class SplitCheckoutController < ::BaseController include OrderStockCheck include Spree::BaseHelper include CheckoutCallbacks + include CablecarResponses helper 'terms_and_conditions' helper 'checkout' @@ -25,7 +26,11 @@ class SplitCheckoutController < ::BaseController redirect_to_step else flash.now[:error] = I18n.t('split_checkout.errors.global') - render :edit + + render operations: cable_car. + replace("#checkout", partial("split_checkout/checkout")). + replace("#flashes", partial("shared/flashes", locals: { flashes: flash })), + status: :unprocessable_entity end end diff --git a/app/views/layouts/darkswarm.html.haml b/app/views/layouts/darkswarm.html.haml index de1f90b8fa..c02ebb6ee0 100644 --- a/app/views/layouts/darkswarm.html.haml +++ b/app/views/layouts/darkswarm.html.haml @@ -15,17 +15,27 @@ %link{href: "https://fonts.googleapis.com/css?family=Roboto:400,300italic,400italic,300,700,700italic|Oswald:300,400,700", rel: "stylesheet", type: "text/css"} %link{href: font_path("OFN-v2.woff"), rel: "preload", as: "font", crossorigin: "anonymous"} - = stylesheet_link_tag "darkswarm/all" - = javascript_pack_tag "application" - = csrf_meta_tags + = stylesheet_link_tag "darkswarm/all", "data-turbo-track": "reload" + = javascript_pack_tag "application", "data-turbo-track": "reload" - %body{ class: body_classes, "body-scroll" => true , ng: { app: 'Darkswarm' }} + = render "layouts/shopfront_script" if @shopfront_layout + = render "layouts/bugsnag_js" + + - if Spree::Config.stripe_connect_enabled + = render "shared/stripe_js" + + = javascript_include_tag "darkswarm/all", "data-turbo-track": "reload" + = javascript_include_tag "web/all", "data-turbo-track": "reload" + = render "layouts/i18n_script" + + = csrf_meta_tags + %meta{name: "turbo-cache-control", content: "no-cache"} + + %body{ class: body_classes, "body-scroll": "true", "data-turbo": "false" } / [if lte IE 8] = render partial: "shared/ie_warning" = javascript_include_tag "iehack" - = render "layouts/shopfront_script" if @shopfront_layout - .off-canvas-wrap{ offcanvas: true } .fixed.off-canvas-fixed = render "shared/menu/menu" unless @hide_menu @@ -38,16 +48,7 @@ #footer %loading - = render "layouts/bugsnag_js" - - - if Spree::Config.stripe_connect_enabled - = render "shared/stripe_js" - = javascript_include_tag "darkswarm/all" - = javascript_include_tag "web/all" - = render "layouts/i18n_script" - = yield :scripts - = inject_current_hub = inject_current_user = inject_rails_flash diff --git a/app/views/layouts/registration.html.haml b/app/views/layouts/registration.html.haml index 815bff62c2..b8bb3d392e 100644 --- a/app/views/layouts/registration.html.haml +++ b/app/views/layouts/registration.html.haml @@ -11,9 +11,12 @@ %link{href: "https://fonts.googleapis.com/css?family=Roboto:400,300italic,400italic,300,700,700italic|Oswald:300,400,700", rel: "stylesheet", type: "text/css"} = stylesheet_link_tag "darkswarm/all" + = javascript_include_tag "darkswarm/all" + = javascript_pack_tag "application" + = csrf_meta_tags - %body.off-canvas{"ng-app" => "Darkswarm", style: "background-image: url(#{image_path('tile-wide.png')})" } + %body.off-canvas{ style: "background-image: url(#{image_path('tile-wide.png')})", "data-turbo": "false" } / [if lte IE 8] = render partial: "shared/ie_warning" = javascript_include_tag "iehack" @@ -27,10 +30,7 @@ #footer %loading - %script{src: "//maps.googleapis.com/maps/api/js?libraries=places#{ ENV['GOOGLE_MAPS_API_KEY'] ? '&key=' + ENV['GOOGLE_MAPS_API_KEY'] : ''}"} - = javascript_include_tag "darkswarm/all" = yield :scripts - = inject_current_user = yield :injection_data diff --git a/app/views/shared/_flashes.html.haml b/app/views/shared/_flashes.html.haml new file mode 100644 index 0000000000..1cd0bd5615 --- /dev/null +++ b/app/views/shared/_flashes.html.haml @@ -0,0 +1,7 @@ +#flashes + - if defined? flashes + - flashes.each do |type, msg| + %alert.animate-show{"data-controller": "flash"} + %div{type: "#{type}", class: "alert-box #{type == 'error' ? 'alert' : type}"} + %span= msg + %a.small.close{"data-action": "click->flash#close"} × diff --git a/app/views/shared/menu/_menu.html.haml b/app/views/shared/menu/_menu.html.haml index 4559434a8f..cf622767e8 100644 --- a/app/views/shared/menu/_menu.html.haml +++ b/app/views/shared/menu/_menu.html.haml @@ -1,6 +1,9 @@ %div{'ng-controller' => 'CartDropdownCtrl'} = render "shared/menu/large_menu" + %ofn-flash + = render partial: "shared/flashes" + = render "shared/menu/mobile_menu" = render "shared/menu/offcanvas_menu" = render "shared/menu/cart_sidebar" diff --git a/app/views/split_checkout/_checkout.html.haml b/app/views/split_checkout/_checkout.html.haml new file mode 100644 index 0000000000..f56be8a301 --- /dev/null +++ b/app/views/split_checkout/_checkout.html.haml @@ -0,0 +1,4 @@ +%checkout.row#checkout + .small-12.medium-12.columns + = render partial: "split_checkout/tabs" + = render partial: "split_checkout/form" diff --git a/app/views/split_checkout/_form.html.haml b/app/views/split_checkout/_form.html.haml index ebe564b3b5..49469f4e7d 100644 --- a/app/views/split_checkout/_form.html.haml +++ b/app/views/split_checkout/_form.html.haml @@ -2,5 +2,7 @@ = inject_saved_credit_cards %div.checkout-step - = form_with url: checkout_update_path(checkout_step), model: @order, method: :put do |f| - = render "split_checkout/#{checkout_step}", f: f + = form_with url: checkout_update_path(checkout_step), model: @order, method: :put, + data: { remote: "true" } do |form| + + = render "split_checkout/#{checkout_step}", f: form diff --git a/app/views/split_checkout/edit.html.haml b/app/views/split_checkout/edit.html.haml index 17afe2a845..282da26f2c 100644 --- a/app/views/split_checkout/edit.html.haml +++ b/app/views/split_checkout/edit.html.haml @@ -1,7 +1,7 @@ - content_for(:title) do = t :checkout_title -.darkswarm.footer-pad +.darkswarm.footer-pad{"data-turbo": "true"} - content_for :order_cycle_form do %closing = t :checkout_now @@ -19,10 +19,6 @@ .sub-header.show-for-medium-down = render partial: "shopping_shared/order_cycles" - %checkout.row - .small-12.medium-12.columns - = render partial: "split_checkout/tabs" - = render partial: "split_checkout/form" - + = render partial: "checkout" = render partial: "shared/footer" diff --git a/app/views/spree/orders/form/_update_buttons.html.haml b/app/views/spree/orders/form/_update_buttons.html.haml index 884cea6746..65e3e9cbf1 100644 --- a/app/views/spree/orders/form/_update_buttons.html.haml +++ b/app/views/spree/orders/form/_update_buttons.html.haml @@ -12,7 +12,7 @@ - if order.changes_allowed? .columns.show-for-medium-up.medium-3   .columns.small-12.medium-3 - = link_to main_app.cancel_order_path(@order), method: :put, :class => "button secondary expand", "confirm-link-click" => t('orders_confirm_cancel') do + = link_to main_app.cancel_order_path(@order), method: :put, class: "button secondary expand", "data-confirm": t('orders_confirm_cancel') do %i.ofn-i_009-close = t(:cancel_order) .columns.small-12.medium-3 diff --git a/app/views/spree/users/_open_orders.html.haml b/app/views/spree/users/_open_orders.html.haml index 73be12b346..45f1426cb3 100644 --- a/app/views/spree/users/_open_orders.html.haml +++ b/app/views/spree/users/_open_orders.html.haml @@ -21,4 +21,4 @@ %td.order6.text-right.brick %a{"ng-href" => "{{::order.path}}" }= t('.edit') %td.order7.show-for-large-up.text-right - = link_to t('.cancel'), "", method: :put, "ng-href" => "{{::order.cancel_path}}", "confirm-link-click" => t('orders_confirm_cancel') + = link_to t('.cancel'), "", method: :put, "ng-href": "{{::order.cancel_path}}", "data-confirm": t('orders_confirm_cancel') diff --git a/app/webpacker/controllers/flash_controller.js b/app/webpacker/controllers/flash_controller.js new file mode 100644 index 0000000000..12e499ae69 --- /dev/null +++ b/app/webpacker/controllers/flash_controller.js @@ -0,0 +1,20 @@ +import { Controller } from "stimulus" + +document.addEventListener('turbolinks:before-cache', () => + document.getElementById('flash').remove() +) + +export default class extends Controller { + connect() { + setTimeout(this.fadeout.bind(this), 3000) + } + + fadeout() { + this.element.classList.add("animate-hide-500") + setTimeout(this.close.bind(this), 500) + } + + close() { + this.element.remove() + } +} diff --git a/app/webpacker/packs/application.js b/app/webpacker/packs/application.js index fdd6b29cb2..969633e0d5 100644 --- a/app/webpacker/packs/application.js +++ b/app/webpacker/packs/application.js @@ -7,3 +7,15 @@ import { definitionsFromContext } from "stimulus/webpack-helpers" const application = Application.start() const context = require.context("controllers", true, /.js$/) application.load(definitionsFromContext(context)) + +import CableReady from "cable_ready" +import mrujs from "mrujs" +import { CableCar } from "mrujs/plugins" +import * as Turbo from "@hotwired/turbo" + +window.Turbo = Turbo +mrujs.start({ + plugins: [ + new CableCar(CableReady) + ] +}) diff --git a/config/application.rb b/config/application.rb index 800cff8ff7..0789e6ab9b 100644 --- a/config/application.rb +++ b/config/application.rb @@ -8,7 +8,7 @@ require "rails" "action_view/railtie", "action_mailer/railtie", "active_job/railtie", - #"action_cable/engine", # Enable this when installing StimulusReflex + "action_cable/engine", #"action_mailbox/engine", #"action_text/engine", "rails/test_unit/railtie", diff --git a/config/webpacker.yml b/config/webpacker.yml index f966a6ac93..dccab3e4ab 100644 --- a/config/webpacker.yml +++ b/config/webpacker.yml @@ -71,15 +71,7 @@ development: watch_options: ignored: '**/node_modules/**' - -test: - <<: *default - compile: true - - # Compile test packs to a separate directory - public_output_path: packs-test - -production: +production: &production <<: *default # Production depends on precompilation of packs prior to booting for performance. @@ -90,3 +82,9 @@ production: # Cache manifest.json for performance cache_manifest: true + +test: + <<: *production + + # Compile test packs to a separate directory + public_output_path: packs-test diff --git a/package.json b/package.json index 0149e6af18..ed4d90ce83 100644 --- a/package.json +++ b/package.json @@ -27,9 +27,12 @@ }, "license": "AGPL-3.0", "dependencies": { + "@hotwired/turbo": "^7.0.0-rc.4", "@rails/webpacker": "5.4.2", + "cable_ready": "^5.0.0-pre2", "flatpickr": "^4.6.9", "moment": "^2.29.1", + "mrujs": "^0.4.13", "shortcut-buttons-flatpickr": "^0.3.1", "stimulus": "^2.0.0", "webpack": "^4.46.0", diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index b975f5aff7..c912bb80d1 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -55,6 +55,12 @@ RSpec.configure do |config| Capybara.reset_sessions! end + # Precompile Webpacker assets (once) when starting the suite. The default setup can result + # in the assets getting compiled many times throughout the build, slowing it down. + config.before :suite do + Webpacker.compile + end + # Fix encoding issue in Rails 5.0; allows passing empty arrays or hashes as params. config.before(:each, type: :controller) { @request.env["CONTENT_TYPE"] = 'application/json' } diff --git a/yarn.lock b/yarn.lock index bc0b0ddcde..58c6facb51 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1599,6 +1599,11 @@ resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.2.5.tgz#8eed982e2ee6f7f4e44c253e12962980791efd46" integrity sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA== +"@hotwired/turbo@^7.0.0-rc.4": + version "7.0.0-rc.4" + resolved "https://registry.yarnpkg.com/@hotwired/turbo/-/turbo-7.0.0-rc.4.tgz#d3ab9555544534f5ec649613553e72ff6c7d7122" + integrity sha512-4qx+6O6mUN+cSN+ZLGCOGc+2MxNrs7cFbmnWD6LIfiHAQyuNiIuB87Y5IAtOo8xj16fOBd2CdU1WRJya4Wkw0A== + "@istanbuljs/load-nyc-config@^1.0.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" @@ -3964,6 +3969,13 @@ bytes@3.1.0: resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== +cable_ready@^5.0.0-pre2: + version "5.0.0-pre2" + resolved "https://registry.yarnpkg.com/cable_ready/-/cable_ready-5.0.0-pre2.tgz#c3589ebfe28a10db3998ae3711d31a072be53bfb" + integrity sha512-/Ql2e/Hz0kRRKzzz06sMXFm3+/qacYqSHfWkdt1CcsI7I6OOOhHzPAgY8VS+zqa/6+ggjWoPqHyi8Hr6j/0O6w== + dependencies: + morphdom "^2.6.1" + cacache@^12.0.2: version "12.0.4" resolved "https://registry.yarnpkg.com/cacache/-/cacache-12.0.4.tgz#668bcbd105aeb5f1d92fe25570ec9525c8faa40c" @@ -8787,6 +8799,11 @@ moment@^2.29.1: resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.1.tgz#b2be769fa31940be9eeea6469c075e35006fa3d3" integrity sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ== +"morphdom@>=2.6.0 <3.0.0", morphdom@^2.6.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/morphdom/-/morphdom-2.6.1.tgz#e868e24f989fa3183004b159aed643e628b4306e" + integrity sha512-Y8YRbAEP3eKykroIBWrjcfMw7mmwJfjhqdpSvoqinu8Y702nAwikpXcNFDiIkyvfCLxLM9Wu95RZqo4a9jFBaA== + move-concurrently@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92" @@ -8799,6 +8816,13 @@ move-concurrently@^1.0.1: rimraf "^2.5.4" run-queue "^1.0.3" +mrujs@^0.4.13: + version "0.4.13" + resolved "https://registry.yarnpkg.com/mrujs/-/mrujs-0.4.13.tgz#0216d80beeda0711aebb60cf5272265fad34d9a4" + integrity sha512-/MgWDZt13LV515tsblbV8G/2AOR3tPX/CVUI9ppnwjDFU53xlVv/HRKlKDe9EcQZbSYiALyb0b0SZlp2iPXWTw== + dependencies: + morphdom ">=2.6.0 <3.0.0" + ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"