diff --git a/.babelrc b/.babelrc index 0b10d107b..746d17f73 100644 --- a/.babelrc +++ b/.babelrc @@ -3,14 +3,32 @@ [ "@babel/preset-env", { - "useBuiltIns": "entry" + "useBuiltIns": "usage", + "corejs": 3, + "modules": false } ] ], - "plugins": [ + "babel-plugin-macros", "@babel/plugin-syntax-dynamic-import", - "@babel/plugin-syntax-object-rest-spread", - "@babel/plugin-proposal-class-properties" - ] -} + "@babel/plugin-proposal-class-properties", + "@babel/plugin-transform-runtime" + ], + "env": { + "test": { + "presets": [ + [ + "@babel/preset-env", + { + "targets": { "node": "current" }, + "modules": "commonjs" + } + ] + ], + "plugins": [ + "babel-plugin-dynamic-import-node" + ] + } + } +} \ No newline at end of file diff --git a/.browserslistrc b/.browserslistrc index e94f8140c..24a8d0f62 100644 --- a/.browserslistrc +++ b/.browserslistrc @@ -1 +1,3 @@ -defaults +> 0.2% +not dead +not op_mini all diff --git a/.eslintrc.json b/.eslintrc.json deleted file mode 100644 index 1565e4d2c..000000000 --- a/.eslintrc.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "env": { - "browser": true, - "es6": true - }, - "extends": [ - "plugin:vue/essential", - "eslint:recommended" - ], - "parserOptions": { - "sourceType": "module" - }, - "rules": { - "indent": [ - "error", - 2 - ], - "linebreak-style": [ - "error", - "unix" - ], - "quotes": [ - "error", - "single" - ], - "semi": [ - "error", - "always" - ] - } -} diff --git a/.gitignore b/.gitignore index f88fa113e..f84aa0b91 100644 --- a/.gitignore +++ b/.gitignore @@ -37,19 +37,14 @@ yarn-error\.log /node_modules yarn-debug.log* .yarn-integrity +/app/assets/builds/* +!/app/assets/builds/.keep # Ignore master key for decrypting credentials and more. /config/master.key -/public/packs -/public/packs-test -/node_modules -/yarn-error.log -yarn-debug.log* -.yarn-integrity - # Ignore Jetbrains IDE files /.idea # Ignore gemini-Cli files -gemini.md \ No newline at end of file +gemini.md diff --git a/.postcssrc.yml b/.postcssrc.yml deleted file mode 100644 index 150dac3c6..000000000 --- a/.postcssrc.yml +++ /dev/null @@ -1,3 +0,0 @@ -plugins: - postcss-import: {} - postcss-cssnext: {} diff --git a/.sass-lint.yml b/.sass-lint.yml deleted file mode 100644 index e0890ee51..000000000 --- a/.sass-lint.yml +++ /dev/null @@ -1,29 +0,0 @@ -files: - include: 'app/**/*.s+(a|c)ss' - -rules: - indentation: - - 2 - - - size: 2 - - property-sort-order: - - 2 - - - # http://rhodesmill.org/brandon/2011/concentric-css/ - order: 'concentric' - - force-element-nesting: - - 2 - - force-pseudo-nesting: - - 2 - - single-line-per-selector: - - 2 - - no-qualifying-elements: - - 2 - - leading-zero: - - 2 diff --git a/.slim-lint.yml b/.slim-lint.yml deleted file mode 100644 index 9f7eafc3d..000000000 --- a/.slim-lint.yml +++ /dev/null @@ -1,4 +0,0 @@ -linters: - - LineLength: - max: 120 diff --git a/.stylelintrc.json b/.stylelintrc.json new file mode 100644 index 000000000..b5b3e9010 --- /dev/null +++ b/.stylelintrc.json @@ -0,0 +1,17 @@ +{ + "extends": [ + "stylelint-config-standard-scss", + "stylelint-config-recess-order" + ], + "rules": { + "selector-no-qualifying-type": [true, { + "ignore" : ["attribute", "class", "id"] + }] + }, + "overrides": [ + { + "files": ["**/*.vue"], + "customSyntax": "postcss-html" + } + ] +} \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index f5cb658fa..8bc2117bf 100644 --- a/Dockerfile +++ b/Dockerfile @@ -19,7 +19,7 @@ RUN apt-get update -qq && \ libyaml-dev # Add Node, required for asset pipeline. -RUN curl -sL https://deb.nodesource.com/setup_16.x | bash - && \ +RUN curl -sL https://deb.nodesource.com/setup_18.x | bash - && \ apt-get install -y nodejs && \ npm install -q -g yarn diff --git a/Gemfile b/Gemfile index 45b02644b..05104b136 100644 --- a/Gemfile +++ b/Gemfile @@ -3,14 +3,16 @@ source 'https://rubygems.org' gem 'bcrypt', '~> 3.1.20' gem 'bootsnap', '~> 1.18.6' gem 'browser', '~> 6.2.0' +gem 'cssbundling-rails', '~> 1.4' +gem 'dartsass-rails', '~> 0.5.1' gem 'devise', '~>4.9.4' gem 'devise-i18n', '~>1.15.0' gem 'factory_bot_rails', '~> 6.5.1' gem 'faker', '~> 3.5.2' -gem 'font-awesome-rails', '~> 4.7.0.9' gem 'http', '~> 5.3.1' gem 'jbuilder', '~> 2.14.1' gem 'jquery-rails', '~> 4.6.1' +gem 'jsbundling-rails', '~> 1.3' gem 'kaminari', '~> 1.2.2' gem 'mollie-api-ruby', '~> 4.18.0' gem 'net-imap', '~> 0.5.12' @@ -29,17 +31,16 @@ gem 'rails', '~> 7.2.2', '>= 7.2.2.2' gem 'rails-i18n', '~> 7.0.10' gem 'redis-rails', '~> 5.0.2' gem 'rest-client', '~> 2.1.0' -gem 'sassc-rails', '~> 2.1.2' gem 'sentry-rails', '~> 5.28', '>= 5.28.1' gem 'sentry-ruby', '~> 5.28', '>= 5.28.1' gem 'sentry-sidekiq', '~> 5.28', '>= 5.28.1' gem 'sidekiq', '~> 8.0.8' gem 'sidekiq-scheduler', '~> 6.0.1' gem 'simple_form', '~> 5.4.0' -gem 'turbolinks', '~> 5.2.1' +gem 'sprockets-rails', '~> 3.5' +gem 'turbo-rails', '~> 2.0' gem 'uglifier', '~> 4.2.1' gem 'validates_timeliness', '~> 7.1.0' -gem 'webpacker', '~> 5.4.4' gem 'wicked_pdf', '~> 2.8.2' gem 'wkhtmltopdf-binary', '~> 0.12.6.10' diff --git a/Gemfile.lock b/Gemfile.lock index 1bf4502e4..12e45aa9e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -113,6 +113,11 @@ GEM concurrent-ruby (1.3.5) connection_pool (2.5.4) crass (1.0.6) + cssbundling-rails (1.4.3) + railties (>= 6.0.0) + dartsass-rails (0.5.1) + railties (>= 6.0.0) + sass-embedded (~> 1.63) database_consistency (2.0.6) activerecord (>= 3.2) date (3.4.1) @@ -155,13 +160,10 @@ GEM logger faraday-net_http (3.4.1) net-http (>= 0.5.0) - ffi (1.17.2) ffi (1.17.2-x86_64-linux-gnu) ffi-compiler (1.3.2) ffi (>= 1.15.5) rake - font-awesome-rails (4.7.0.9) - railties (>= 3.2, < 9.0) foreman (0.90.0) thor (~> 1.4) formatador (1.2.1) @@ -171,6 +173,9 @@ GEM raabro (~> 1.4) globalid (1.3.0) activesupport (>= 6.1) + google-protobuf (4.33.0-x86_64-linux-gnu) + bigdecimal + rake (>= 13) guard (2.19.1) formatador (>= 0.2.4) listen (>= 2.7, < 4.0) @@ -217,6 +222,8 @@ GEM rails-dom-testing (>= 1, < 3) railties (>= 4.2.0) thor (>= 0.14, < 2.0) + jsbundling-rails (1.3.1) + railties (>= 6.0.0) json (2.15.2) jwt (3.1.2) base64 @@ -352,8 +359,6 @@ GEM base64 (>= 0.1.0) logger (>= 1.6.0) rack (>= 3.0.0, < 4) - rack-proxy (0.7.7) - rack rack-session (2.1.1) base64 (>= 0.1.0) rack (>= 3.0.0) @@ -499,16 +504,9 @@ GEM ruby-progressbar (1.13.0) rufus-scheduler (3.9.2) fugit (~> 1.1, >= 1.11.1) - sassc (2.4.0) - ffi (~> 1.9) - sassc-rails (2.1.2) - railties (>= 4.0.0) - sassc (>= 2.0) - sprockets (> 3.0) - sprockets-rails - tilt + sass-embedded (1.93.2-x86_64-linux-gnu) + google-protobuf (~> 4.31) securerandom (0.4.1) - semantic_range (3.1.0) sentry-rails (5.28.1) railties (>= 5.0) sentry-ruby (~> 5.28.1) @@ -565,14 +563,13 @@ GEM stringio (3.1.7) terminal-notifier-guard (1.7.0) thor (1.4.0) - tilt (2.6.1) timecop (0.9.10) timeliness (0.5.3) timeout (0.4.3) tsort (0.2.0) - turbolinks (5.2.1) - turbolinks-source (~> 5.2) - turbolinks-source (5.2.0) + turbo-rails (2.0.17) + actionpack (>= 7.1.0) + railties (>= 7.1.0) tzinfo (2.0.6) concurrent-ruby (~> 1.0) uglifier (4.2.1) @@ -594,11 +591,6 @@ GEM activemodel (>= 6.0.0) bindex (>= 0.4.0) railties (>= 6.0.0) - webpacker (5.4.4) - activesupport (>= 5.2) - rack-proxy (>= 0.6.1) - railties (>= 5.2) - semantic_range (>= 2.3.0) websocket-driver (0.8.0) base64 websocket-extensions (>= 0.1.0) @@ -622,19 +614,21 @@ DEPENDENCIES bullet (~> 8.1) capistrano-sidekiq (~> 3.2.0) colorize (~> 1.1.0) + cssbundling-rails (~> 1.4) + dartsass-rails (~> 0.5.1) database_consistency (~> 2.0.6) devise (~> 4.9.4) devise-i18n (~> 1.15.0) dotenv-rails (~> 3.1.8) factory_bot_rails (~> 6.5.1) faker (~> 3.5.2) - font-awesome-rails (~> 4.7.0.9) foreman (~> 0.90.0) guard-livereload (~> 2.5.2) guard-rspec (~> 4.7.3) http (~> 5.3.1) jbuilder (~> 2.14.1) jquery-rails (~> 4.6.1) + jsbundling-rails (~> 1.3) kaminari (~> 1.2.2) listen (~> 3.9.0) mina (~> 1.2.5) @@ -666,7 +660,6 @@ DEPENDENCIES rubocop-rails (~> 2.33, >= 2.33.4) rubocop-rspec (~> 3.7) rubocop-rspec_rails (~> 2.31) - sassc-rails (~> 2.1.2) sentry-rails (~> 5.28, >= 5.28.1) sentry-ruby (~> 5.28, >= 5.28.1) sentry-sidekiq (~> 5.28, >= 5.28.1) @@ -678,14 +671,14 @@ DEPENDENCIES spring (~> 4.4.0) spring-commands-rspec (~> 1.0.4) spring-watcher-listen (~> 2.1.0) + sprockets-rails (~> 3.5) terminal-notifier-guard (~> 1.7.0) timecop (~> 0.9.10) - turbolinks (~> 5.2.1) + turbo-rails (~> 2.0) tzinfo-data uglifier (~> 4.2.1) validates_timeliness (~> 7.1.0) web-console (~> 4.2.1) - webpacker (~> 5.4.4) wicked_pdf (~> 2.8.2) wkhtmltopdf-binary (~> 0.12.6.10) diff --git a/Procfile.dev b/Procfile.dev new file mode 100644 index 000000000..43717fdeb --- /dev/null +++ b/Procfile.dev @@ -0,0 +1,3 @@ +web: env RUBY_DEBUG_OPEN=true bin/rails server -b 0.0.0.0 +js: NODE_ENV=development yarn watch +css: yarn build:css --watch diff --git a/README.md b/README.md index 02fea7872..e259e4ea2 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ Alpha SOFIA [![Continuous Delivery](https://github.com/csvalpha/sofia/actions/workflows/continuous-delivery.yml/badge.svg)](https://github.com/csvalpha/sofia/actions/workflows/continuous-delivery.yml) [![codecov](https://codecov.io/github/csvalpha/sofia/graph/badge.svg?token=RGR5PARLD5)](https://codecov.io/github/csvalpha/sofia) -The source code belonging to Alpha SOFIA. It is a system built with Ruby on Rails with Turbolinks and a little VueJS, used to manage orders in our own bar "Flux". Users authenticate via OAuth API (currently "Alpha AMBER") or through the builtin login portal to see how much credit they got left, or to be able to register new orders and/or payments. +The source code belonging to Alpha SOFIA. It is a system built with Ruby on Rails with Turbo and a little VueJS, used to manage orders in our own bar "Flux". Users authenticate via OAuth API (currently "Alpha AMBER") or through the built-in login portal to see how much credit they have left, or to register new orders and/or payments. Use this repository to build upon, use as-is, learn from it, prove a point or whatever 😏 diff --git a/app/.gitattributes b/app/.gitattributes new file mode 100644 index 000000000..a9fc77db5 --- /dev/null +++ b/app/.gitattributes @@ -0,0 +1,2 @@ +# Default to LF for most text files +* text=auto eol=lf diff --git a/app/assets/builds/.keep b/app/assets/builds/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/app/assets/config/manifest.js b/app/assets/config/manifest.js index b16e53d6d..9a99757a4 100644 --- a/app/assets/config/manifest.js +++ b/app/assets/config/manifest.js @@ -1,3 +1,2 @@ //= link_tree ../images -//= link_directory ../javascripts .js -//= link_directory ../stylesheets .css +//= link_tree ../builds diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js deleted file mode 100644 index bdd70a3e5..000000000 --- a/app/assets/javascripts/application.js +++ /dev/null @@ -1,36 +0,0 @@ -// This is a manifest file that'll be compiled into application.js, which will include all the files -// listed below. -// -// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, or any plugin's -// vendor/assets/javascripts directory can be referenced here using a relative path. -// -// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the -// compiled file. JavaScript code in this file should be added after the last require_* statement. -// -// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details -// about supported directives. -// -//= require rails-ujs -//= require turbolinks -//= require jquery3 -//= require bootstrap.bundle.min.js -//= require webfontloader.js -//= require turbolinks-animate/src/index.js -//= require_tree . - -/* eslint-disable no-undef */ -WebFont.load({ - google: { - families: ['Roboto:300,400,500'] - } -}); - -document.addEventListener( 'turbolinks:load', function() { - TurbolinksAnimate.init({ - element: document.querySelector('main'), - animation: 'fadein', - duration: '0.15s', - }); -}); - -/* eslint-enable no-undef */ diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index 1bf012c17..085224c7b 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -1,7 +1,5 @@ +@import 'bootstrap/scss/bootstrap'; @import 'theme_sofia'; -@import 'bootstrap'; -@import 'font-awesome'; - @import 'order_screen'; @import 'price_lists'; @@ -29,16 +27,16 @@ a { .slide-fade-enter, .slide-fade-leave-to { - transform: translateX(10px); opacity: 0; + transform: translateX(10px); } // Source: jsfiddle.net/mwj2tagh .fa-plus18 { - text-align: center; - font-family: 'helvetica neue', Helvetica, Arial, Sans-Serif; + font-family: 'helvetica neue', Helvetica, Arial, sans-serif; font-size: 80%; font-weight: bold; + text-align: center; &::before { content: '18+'; @@ -80,10 +78,10 @@ a { .footer { position: absolute; bottom: 0; - background-color: $gray-400; width: 100%; height: 48px; line-height: 48px; + background-color: $gray-400; } .footer-padding { diff --git a/app/assets/stylesheets/order_screen.scss b/app/assets/stylesheets/order_screen.scss index 27af62c2d..0735535ba 100644 --- a/app/assets/stylesheets/order_screen.scss +++ b/app/assets/stylesheets/order_screen.scss @@ -1,76 +1,23 @@ +@import 'bootstrap/scss/bootstrap'; @import 'theme_sofia'; -@import 'bootstrap'; + .order-screen { display: grid; - + grid-template-rows: [header-start] 80px [header-end user-details-start product-grid-start orders-start order-grid-start] 1fr [user-details-end orders-end product-grid-end order-grid-end]; + grid-template-columns: [header-start orders-start user-details-start] minmax(35%, 340px) [user-details-end orders-end product-grid-start order-grid-start] 1fr [header-end product-grid-end order-grid-end]; width: 100vw; height: 100vh; - grid-template-columns: [header-start orders-start user-details-start] minmax(35%, 340px) [user-details-end orders-end product-grid-start order-grid-start] 1fr [header-end product-grid-end order-grid-end]; - grid-template-rows: [header-start] 80px [header-end user-details-start product-grid-start orders-start order-grid-start] 1fr [user-details-end orders-end product-grid-end order-grid-end]; - - .header { - display: flex; - - flex-flow: row nowrap; - justify-content: space-between; - z-index: 10; - - box-shadow: 0 1px 4px $transparent-200; - background-color: $gray-100; - - color: $font-color-dark; - - grid-area: header; - } - - .header-nav { - display: flex; - flex: 1; - - flex-flow: row nowrap; - align-items: center; - align-self: flex-start; - justify-content: start; - - margin: 0; - padding: 0; - - height: 100%; - - list-style: none; - - line-height: 20pt; - font-size: $font-size-xl; - } - - .header-nav-item { - padding: 0 1rem; - } - - .header-nav-home { - a { - i { - padding: 0; - padding-left: 1rem; - color: $gray-600; - } - } - } - .flash { display: flex; align-self: flex-end; - - background-color: $gray-800; height: 100%; - + font-size: $font-size-lg; vertical-align: middle; - text-align: center; - color: $font-color-light; - font-size: $font-size-lg; + text-align: center; + background-color: $gray-800; } .flash-text { @@ -114,28 +61,75 @@ color: inherit; } + .orders-rows-row-count { + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-between; + + i { + color: $font-color-medium; + } + } + + .header { + z-index: 10; + display: flex; + flex-flow: row nowrap; + grid-area: header; + justify-content: space-between; + color: $font-color-dark; + background-color: $gray-100; + box-shadow: 0 1px 4px $transparent-200; + } + + .header-nav { + display: flex; + flex: 1; + flex-flow: row nowrap; + align-items: center; + align-self: flex-start; + justify-content: start; + height: 100%; + padding: 0; + margin: 0; + font-size: $font-size-xl; + line-height: 20pt; + list-style: none; + } + + .header-nav-item { + padding: 0 1rem; + } + + .header-nav-home { + a { + i { + padding: 0; + padding-left: 1rem; + color: $gray-600; + } + } + } + .side-panel { + z-index: 4; display: flex; flex-flow: column nowrap; + grid-area: user-details; align-items: stretch; justify-content: flex-start; - - z-index: 4; - + overflow-y: auto; + color: $font-color-dark; + background-color: $gray-200; border-right: 2px solid $gray-400; box-shadow: 2px 0 4px -2px $transparent-200; - background-color: $gray-200; - color: $font-color-dark; - overflow-y: auto; - - grid-area: user-details; } .user-details { + z-index: 5; display: flex; flex-flow: column nowrap; - - z-index: 5; overflow-y: auto; .highlight { @@ -144,19 +138,16 @@ } .user-details-search { - flex-shrink: 0; - z-index: 6; - - border-bottom: 1px solid $gray-400; + flex-shrink: 0; padding: 1.5rem; + border-bottom: 1px solid $gray-400; } .user-details-seperator { - text-align: center; - - color: $font-color-medium; font-size: $font-size-lg; + color: $font-color-medium; + text-align: center; } .user-details-cash-button { @@ -176,22 +167,19 @@ } .user-details-suggestions { + z-index: 6; display: flex; flex-flow: column nowrap; - - z-index: 6; overflow-y: auto; } .user-details-user { z-index: 6; - border-bottom: 1px solid $gray-400; } .user-details-suggestions-user { flex-shrink: 0; - border-bottom: 1px solid $gray-400; &.highlight, @@ -201,11 +189,10 @@ } .orders { + z-index: 5; display: flex; - flex-flow: column nowrap; flex-grow: 1; - - z-index: 5; + flex-flow: column nowrap; & > * { flex: 0 1 auto; @@ -223,27 +210,14 @@ .orders-rows-row { align-items: center; - - border-top: 1px solid $gray-400; - font-size: $font-size-lg; + border-top: 1px solid $gray-400; &:last-child { border-bottom: 1px solid $gray-400; } } - .orders-rows-row-count { - display: flex; - flex-direction: row; - align-items: center; - justify-content: space-between; - - i { - color: $font-color-medium; - } - } - .orders-rows-total { font-size: $font-size-lg; } @@ -253,23 +227,20 @@ } .orders-confirmation { - padding: 1rem; width: 100%; - - color: $font-color-light; + padding: 1rem; font-size: $font-size-lg; + color: $font-color-light; } .product-grid { display: grid; + grid-area: product-grid; + grid-template-rows: auto; + grid-template-columns: repeat(4, 1fr); + gap: 2px; justify-content: flex-start; - background-color: $gray-400; - - grid-template-columns: repeat(4, 1fr); - grid-template-rows: auto; - grid-gap: 2px; - grid-area: product-grid; } .product-grid-product { @@ -277,7 +248,6 @@ flex-flow: column nowrap; align-items: center; justify-content: center; - background-color: $gray-100; &:hover { @@ -294,9 +264,9 @@ } .product-grid-product-name { - text-align: center; - color: $font-color-dark; font-size: $font-size-lg; + color: $font-color-dark; + text-align: center; } .fa-circle-lighter { @@ -308,4 +278,4 @@ grid-area: order-grid; overflow-y: auto; } -} +} \ No newline at end of file diff --git a/app/assets/stylesheets/theme_sofia.scss b/app/assets/stylesheets/theme_sofia.scss index 3b985bfda..b2e69ba7e 100644 --- a/app/assets/stylesheets/theme_sofia.scss +++ b/app/assets/stylesheets/theme_sofia.scss @@ -1,8 +1,7 @@ // Basic colors -$brand-primary: #e8df0c; +$brand-primary: #e8df0c; $brand-secondary: #00a5b5; - $gray-100: #f8f9fa; $gray-200: #e9ecef; $gray-300: #dee2e6; @@ -14,24 +13,21 @@ $gray-800: #343a40; $gray-900: #212529; // Transparent blacks -$transparent-200: rgba(0, 0, 0, .2); -$transparent-800: rgba(0, 0, 0, .8); +$transparent-200: rgb(0 0 0 / 20%); +$transparent-800: rgb(0 0 0 / 80%); // Typography -$font-family-sans-serif: Roboto, 'Helvetica Neue', Arial, sans-serif; - -$font-size-base: .93rem; -$font-size-xl: ($font-size-base * 2); - -$font-color-light: $gray-100; -$font-color-medium: $gray-600; -$font-color-dark: $gray-800; - +$font-family-sans-serif: roboto, 'Helvetica Neue', arial, sans-serif; +$font-size-base: .93rem; +$font-size-xl: ($font-size-base * 2); +$font-color-light: $gray-100; +$font-color-medium: $gray-600; +$font-color-dark: $gray-800; $alpha-primary: #ff0; // Basic layout -$body-bg: $gray-100; -$body-color: $font-color-dark; +$body-bg: $gray-100; +$body-color: $font-color-dark; // Custom stuff .table-header-rotated { @@ -40,8 +36,8 @@ $body-color: $font-color-dark; white-space: nowrap; > div { - transform: translate(-9px, 0) rotate(-45deg); width: 30px; + transform: translate(-9px, 0) rotate(-45deg); } > div > a { @@ -51,10 +47,10 @@ $body-color: $font-color-dark; .sofia-header { margin-bottom: .5rem; - line-height: 1.2; - color: inherit; font-family: inherit; font-size: 2.5rem; font-weight: 500; + line-height: 1.2; + color: inherit; } } diff --git a/app/controllers/orders_controller.rb b/app/controllers/orders_controller.rb index e79828b8a..b9f77f45d 100644 --- a/app/controllers/orders_controller.rb +++ b/app/controllers/orders_controller.rb @@ -39,7 +39,7 @@ def create # rubocop:disable Metrics/MethodLength, Metrics/AbcSize end def update - @order = Order.find(permitted_attributes_on_update[:id]) + @order = Order.find(params[:id]) authorize @order @@ -89,7 +89,7 @@ def permitted_attributes end def permitted_attributes_on_update - params.permit(:id, order_rows_attributes: %i[id product_count]) + params.require(:order).permit(order_rows_attributes: %i[id product_count]) end def proper_json diff --git a/app/javascript/packs/activities.js b/app/javascript/activities.js similarity index 57% rename from app/javascript/packs/activities.js rename to app/javascript/activities.js index 7754e20fb..57816e4e5 100644 --- a/app/javascript/packs/activities.js +++ b/app/javascript/activities.js @@ -1,16 +1,10 @@ import Vue from 'vue/dist/vue.esm'; -import TurbolinksAdapter from 'vue-turbolinks'; -import VueResource from 'vue-resource'; -Vue.use(TurbolinksAdapter); -Vue.use(VueResource); +document.addEventListener('turbo:load', () => { + const element = document.getElementById('new_activity_modal'); + if (element) { + const priceLists = JSON.parse(element.dataset.priceLists); -document.addEventListener('turbolinks:load', () => { - Vue.http.headers.common['X-CSRF-TOKEN'] = document.querySelector('meta[name="csrf-token"]').getAttribute('content'); - - var element = document.getElementById('new_activity_modal'); - if (element !== null) { - var price_lists = JSON.parse(element.dataset.priceLists); new Vue({ el: element, data: { @@ -19,7 +13,7 @@ document.addEventListener('turbolinks:load', () => { id: 0, }, open: false, - allSuggestions: price_lists + allSuggestions: priceLists }, computed: { dropdownOpened () { @@ -27,7 +21,7 @@ document.addEventListener('turbolinks:load', () => { }, suggestions () { return this.allSuggestions.filter(value => { - return value.name.indexOf(this.query) >= 0; + return value.name.toLowerCase().indexOf(this.query.toLowerCase()) >= 0; }); } }, @@ -45,4 +39,4 @@ document.addEventListener('turbolinks:load', () => { } }); } -}); +}); \ No newline at end of file diff --git a/app/javascript/activity.js b/app/javascript/activity.js new file mode 100644 index 000000000..450d5d82f --- /dev/null +++ b/app/javascript/activity.js @@ -0,0 +1,24 @@ +import Vue from 'vue/dist/vue.esm'; + +import ProductTotals from './components/activity/ProductTotals.vue'; + +let vueInstance = null; + +document.addEventListener('turbo:before-cache', () => { + if (vueInstance) { + vueInstance.$destroy(); + vueInstance = null; + } +}); + +document.addEventListener('turbo:load', () => { + const element = document.getElementById('activity'); + if (element) { + vueInstance = new Vue({ + el: element, + components: { + ProductTotals + } + }); + } +}); diff --git a/app/javascript/application.js b/app/javascript/application.js new file mode 100644 index 000000000..fd15ec766 --- /dev/null +++ b/app/javascript/application.js @@ -0,0 +1,31 @@ +import { Turbo } from '@hotwired/turbo-rails'; +Turbo.start(); + +import axios from 'axios'; + +import 'jquery'; +import 'bootstrap'; + +import WebFont from 'webfontloader'; +import '@fortawesome/fontawesome-free/css/all.css'; + +WebFont.load({ + google: { + families: ['Roboto:300,400,500'] + } +}); + +axios.interceptors.request.use((config) => { + const csrfToken = document.querySelector('meta[name="csrf-token"]')?.getAttribute('content'); + if (csrfToken) { + config.headers['X-CSRF-Token'] = csrfToken; + } + return config; +}, (error) => { + return Promise.reject(error); +}); + + +document.addEventListener('turbo:load', () => { + +}); \ No newline at end of file diff --git a/app/javascript/components/ProductTable.vue b/app/javascript/components/ProductTable.vue index d9652403a..ff7b81ac3 100644 --- a/app/javascript/components/ProductTable.vue +++ b/app/javascript/components/ProductTable.vue @@ -18,10 +18,10 @@
<% end %> - - - <%= csrf_meta_tags %> - <%= yield(:modal) %> diff --git a/app/views/layouts/errors.html.erb b/app/views/layouts/errors.html.erb index f3459a9ea..a44767d54 100644 --- a/app/views/layouts/errors.html.erb +++ b/app/views/layouts/errors.html.erb @@ -3,8 +3,8 @@ <%= "#{Rails.application.config.x.site_name} – Streepsysteem der #{Rails.application.config.x.site_association}" %> - <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %> - <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %> + <%= stylesheet_link_tag "application", "data-turbo-track": "reload" %> + <%= javascript_include_tag "application", "data-turbo-track": "reload", defer: true %> diff --git a/app/views/partials/_login_prompt.html.erb b/app/views/partials/_login_prompt.html.erb index 0ba91def2..e9baa0ba8 100644 --- a/app/views/partials/_login_prompt.html.erb +++ b/app/views/partials/_login_prompt.html.erb @@ -10,7 +10,7 @@ Log in with a <%= Rails.application.config.x.site_association %> account.

- <%= link_to("Sign in with #{Rails.application.config.x.site_association}", user_amber_oauth2_omniauth_authorize_path, class: 'btn btn-primary', method: :post) %> + <%= link_to "Sign in with #{Rails.application.config.x.site_association}", user_amber_oauth2_omniauth_authorize_path, class: 'btn btn-primary', data: { turbo_method: :post } %>
diff --git a/app/views/partials/_navigation_bar.html.erb b/app/views/partials/_navigation_bar.html.erb index e4ebdf08f..b9c3d5608 100644 --- a/app/views/partials/_navigation_bar.html.erb +++ b/app/views/partials/_navigation_bar.html.erb @@ -10,60 +10,60 @@