diff --git a/.gitignore b/.gitignore index 028a97f09..74f2d2ff1 100644 --- a/.gitignore +++ b/.gitignore @@ -75,4 +75,12 @@ yalc.lock yarn-debug.log* .yarn-integrity -/storybook-static \ No newline at end of file +/storybook-static + +# Vite Ruby +/public/vite* +node_modules +# Vite uses dotenv and suggests to ignore local-only env files. See +# https://vitejs.dev/guide/env-and-mode.html#env-files +*.local + diff --git a/Gemfile b/Gemfile index 144240b62..4f972a33d 100644 --- a/Gemfile +++ b/Gemfile @@ -62,7 +62,7 @@ gem 'activerecord-import' gem 'dotenv-rails' gem 'foreman' gem 'puma' -gem 'webpacker' +gem 'vite_rails' # metrics on heroku gem 'barnes' diff --git a/Gemfile.lock b/Gemfile.lock index 62c6829ed..54b60dc76 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -216,6 +216,7 @@ GEM railties (>= 3.2) down (5.4.0) addressable (~> 2.8) + dry-cli (1.0.0) ecma-re-validator (0.4.0) regexp_parser (~> 2.2) elastic-apm (4.6.2) @@ -570,7 +571,7 @@ GEM rack (>= 1.2.0) rack-protection (3.1.0) rack (~> 2.2, >= 2.2.4) - rack-proxy (0.7.6) + rack-proxy (0.7.7) rack rack-test (2.1.0) rack (>= 1.3) @@ -708,7 +709,6 @@ GEM activerecord (>= 4) activesupport (>= 4) selectize-rails (0.12.6) - semantic_range (3.0.0) sentry-rails (5.14.0) railties (>= 5.0) sentry-ruby (~> 5.14.0) @@ -795,6 +795,13 @@ GEM activemodel (>= 3.2) mail (~> 2.5) version_gem (1.1.2) + vite_rails (3.0.17) + railties (>= 5.1, < 8) + vite_ruby (~> 3.0, >= 3.2.2) + vite_ruby (3.5.0) + dry-cli (>= 0.7, < 2) + rack-proxy (~> 0.6, >= 0.6.1) + zeitwerk (~> 2.2) warden (1.2.9) rack (>= 2.0.9) web-console (4.2.1) @@ -810,11 +817,6 @@ GEM addressable (>= 2.8.0) crack (>= 0.3.2) hashdiff (>= 0.4.0, < 2.0.0) - webpacker (5.4.4) - activesupport (>= 5.2) - rack-proxy (>= 0.6.1) - railties (>= 5.2) - semantic_range (>= 2.3.0) webrick (1.8.1) websocket-driver (0.7.6) websocket-extensions (>= 0.1.0) @@ -956,10 +958,10 @@ DEPENDENCIES tzinfo-data uglifier valid_email2 + vite_rails web-console (>= 4.2.1) web-push webmock - webpacker wisper (= 2.0.0) working_hours diff --git a/Procfile.dev b/Procfile.dev index 73c2af7e8..df7db5d8c 100644 --- a/Procfile.dev +++ b/Procfile.dev @@ -1,4 +1,4 @@ backend: bin/rails s -p 3000 -frontend: export NODE_OPTIONS=--openssl-legacy-provider && bin/webpack-dev-server # https://github.com/mperham/sidekiq/issues/3090#issuecomment-389748695 worker: dotenv bundle exec sidekiq -C config/sidekiq.yml +frontend: bin/vite dev diff --git a/app/javascript/dashboard/assets/scss/_date-picker.scss b/app/javascript/dashboard/assets/scss/_date-picker.scss index 2132d5fd5..a60785e88 100644 --- a/app/javascript/dashboard/assets/scss/_date-picker.scss +++ b/app/javascript/dashboard/assets/scss/_date-picker.scss @@ -1,4 +1,4 @@ -@import '~vue2-datepicker/scss/index'; +@import 'vue2-datepicker/scss/index'; .date-picker { &.no-margin { diff --git a/app/javascript/dashboard/assets/scss/_formulate.scss b/app/javascript/dashboard/assets/scss/_formulate.scss index d683ce3c7..37690a8de 100644 --- a/app/javascript/dashboard/assets/scss/_formulate.scss +++ b/app/javascript/dashboard/assets/scss/_formulate.scss @@ -1,4 +1,4 @@ -@import '~dashboard/assets/scss/variables'; +@import 'dashboard/assets/scss/variables'; .formulate-input { .formulate-input-errors { diff --git a/app/javascript/dashboard/assets/scss/_foundation-settings.scss b/app/javascript/dashboard/assets/scss/_foundation-settings.scss index 3fd834cdd..8f6731993 100644 --- a/app/javascript/dashboard/assets/scss/_foundation-settings.scss +++ b/app/javascript/dashboard/assets/scss/_foundation-settings.scss @@ -41,7 +41,7 @@ // 36. Tooltip // 37. Top Bar -@import '~foundation-sites/scss/util/util'; +@import 'foundation-sites/scss/util/util'; // 1. Global // --------- @@ -51,11 +51,13 @@ $contrast-warnings: false; $global-font-size: 16px; $global-width: 100%; $global-lineheight: 1.5; -$foundation-palette: (primary: $color-woot, +$foundation-palette: ( + primary: $color-woot, secondary: #5d7592, success: #44ce4b, warning: #ffc532, - alert: #ff382d); + alert: #ff382d +); $light-gray: #c0ccda; $medium-gray: #8492a6; $dark-gray: $color-gray; @@ -64,15 +66,15 @@ $white: #fff; $body-background: $white; $body-font-color: $color-body; $body-font-family: 'PlusJakarta', --apple-system, -system-ui, -BlinkMacSystemFont, -"Segoe UI", -Roboto, -"Helvetica Neue", -Tahoma, -Arial, -sans-serif; + -apple-system, + system-ui, + BlinkMacSystemFont, + "Segoe UI", + Roboto, + "Helvetica Neue", + Tahoma, + Arial, + sans-serif; $body-antialiased: true; $global-margin: $space-small; $global-padding: $space-small; @@ -88,7 +90,8 @@ $print-transparent-backgrounds: true; // 2. Breakpoints // -------------- -$breakpoints: (small: 0, +$breakpoints: ( + small: 0, medium: 640px, large: 1024px, xlarge: 1200px, @@ -96,15 +99,19 @@ $breakpoints: (small: 0, xxxlarge: 1600px, ); $print-breakpoint: large; -$breakpoint-classes: (small medium large); +$breakpoint-classes: ( + small medium large +); // 3. The Grid // ----------- $grid-row-width: $global-width; $grid-column-count: 12; -$grid-column-gutter: (small: $zero, - medium: $zero); +$grid-column-gutter: ( + small: $zero, + medium: $zero +); $grid-column-align-edge: true; $block-grid-max: 8; @@ -118,7 +125,8 @@ $font-family-monospace: $body-font-family; $header-color: $color-heading; $header-lineheight: 1.4; $header-margin-bottom: 0.3125rem; -$header-styles: (small: ("h1": ("font-size": 24), +$header-styles: ( + small: ("h1": ("font-size": 24), "h2": ("font-size": 20), "h3": ("font-size": 19), "h4": ("font-size": 18), @@ -129,7 +137,8 @@ $header-styles: (small: ("h1": ("font-size": 24), "h3": ("font-size": 31), "h4": ("font-size": 25), "h5": ("font-size": 20), - "h6": ("font-size": 16))); + "h6": ("font-size": 16)) +); $header-text-rendering: optimizeLegibility; $small-font-size: 80%; $header-small-font-color: $medium-gray; @@ -249,16 +258,18 @@ $button-background-hover: scale-color($button-background, $lightness: -15%); $button-color: $white; $button-color-alt: $white; $button-radius: var(--border-radius-normal); -$button-sizes: (tiny: var(--font-size-micro), +$button-sizes: ( + tiny: var(--font-size-micro), small: var(--font-size-mini), default: var(--font-size-small), - large: var(--font-size-medium)); + large: var(--font-size-medium) +); $button-palette: $foundation-palette; $button-opacity-disabled: 0.4; $button-background-hover-lightness: -20%; $button-hollow-hover-lightness: -50%; $button-transition: background-color 0.25s ease-out, -color 0.25s ease-out; + color 0.25s ease-out; // 12. Button Group // ---------------- @@ -298,12 +309,18 @@ $card-margin: $global-margin; // ---------------- $closebutton-position: right top; -$closebutton-offset-horizontal: (small: 0.66rem, - medium: 1rem); -$closebutton-offset-vertical: (small: 0.33em, - medium: 0.5rem); -$closebutton-size: (small: 1.5em, - medium: 2em); +$closebutton-offset-horizontal: ( + small: 0.66rem, + medium: 1rem +); +$closebutton-offset-vertical: ( + small: 0.33em, + medium: 0.5rem +); +$closebutton-size: ( + small: 1.5em, + medium: 2em +); $closebutton-lineheight: 1; $closebutton-color: $dark-gray; $closebutton-color-hover: $black; @@ -326,9 +343,11 @@ $dropdown-border: 1px solid $medium-gray; $dropdown-font-size: 0.625rem; $dropdown-width: 300px; $dropdown-radius: $global-radius; -$dropdown-sizes: (tiny: 100px, +$dropdown-sizes: ( + tiny: 100px, small: 200px, - large: 400px); + large: 400px +); // 18. Dropdown Menu // ----------------- @@ -423,10 +442,12 @@ $meter-fill-bad: $alert-color; // 24. Off-canvas // -------------- -$offcanvas-sizes: (small: 14.375, +$offcanvas-sizes: ( + small: 14.375, medium: 14.375, ); -$offcanvas-vertical-sizes: (small: 14.375, +$offcanvas-vertical-sizes: ( + small: 14.375, medium: 14.375, ); $offcanvas-background: $light-gray; @@ -486,8 +507,10 @@ $progress-radius: $global-radius; // -------------------- $responsive-embed-margin-bottom: rem-calc(16); -$responsive-embed-ratios: (default: 4 by 3, - widescreen: 16 by 9); +$responsive-embed-ratios: ( + default: 4 by 3, + widescreen: 16 by 9 +); // 29. Reveal // ---------- @@ -541,7 +564,7 @@ $table-padding: rem-calc(8 10 10); $table-hover-scale: 2%; $table-row-hover: darken($table-background, $table-hover-scale); $table-row-stripe-hover: darken($table-background, - $table-color-scale + $table-hover-scale); + $table-color-scale + $table-hover-scale); $table-is-striped: false; $table-striped-background: smart-scale($table-background, $table-color-scale); $table-stripe: even; diff --git a/app/javascript/dashboard/assets/scss/_mixins.scss b/app/javascript/dashboard/assets/scss/_mixins.scss index 2fbb9fa7c..9ca87c859 100644 --- a/app/javascript/dashboard/assets/scss/_mixins.scss +++ b/app/javascript/dashboard/assets/scss/_mixins.scss @@ -1,5 +1,5 @@ -@import '~dashboard/assets/scss/variables'; -@import '~widget/assets/scss/mixins'; +@import 'dashboard/assets/scss/variables'; +@import 'widget/assets/scss/mixins'; $spinner-before-border-color: rgba(255, 255, 255, 0.7); diff --git a/app/javascript/dashboard/assets/scss/_woot.scss b/app/javascript/dashboard/assets/scss/_woot.scss index 2773ced6f..566d79c7a 100644 --- a/app/javascript/dashboard/assets/scss/_woot.scss +++ b/app/javascript/dashboard/assets/scss/_woot.scss @@ -69,7 +69,7 @@ @import 'plugins/multiselect'; @import 'plugins/dropdown'; -@import '~shared/assets/stylesheets/ionicons'; +@import 'shared/assets/stylesheets/ionicons'; @import 'utility-helpers'; .tooltip { diff --git a/app/javascript/dashboard/assets/scss/storybook.scss b/app/javascript/dashboard/assets/scss/storybook.scss index 457560aa9..a5f9692f2 100644 --- a/app/javascript/dashboard/assets/scss/storybook.scss +++ b/app/javascript/dashboard/assets/scss/storybook.scss @@ -10,7 +10,7 @@ @import 'variables'; @import 'vue-multiselect/dist/vue-multiselect.min.css'; -@import '~shared/assets/stylesheets/ionicons'; +@import 'shared/assets/stylesheets/ionicons'; @import 'mixins'; @import 'foundation-settings'; diff --git a/app/javascript/dashboard/components/index.js b/app/javascript/dashboard/components/index.js index ee06ebc9a..7501306ea 100644 --- a/app/javascript/dashboard/components/index.js +++ b/app/javascript/dashboard/components/index.js @@ -1,29 +1,29 @@ /* eslint no-plusplus: 0 */ import AvatarUploader from './widgets/forms/AvatarUploader.vue'; import Bar from './widgets/chart/BarChart'; -import Button from './ui/WootButton'; -import Code from './Code'; -import ColorPicker from './widgets/ColorPicker'; +import Button from './ui/WootButton.vue'; +import Code from './Code.vue'; +import ColorPicker from './widgets/ColorPicker.vue'; import ConfirmDeleteModal from './widgets/modal/ConfirmDeleteModal.vue'; import ConfirmModal from './widgets/modal/ConfirmationModal.vue'; import ContextMenu from './ui/ContextMenu.vue'; import DeleteModal from './widgets/modal/DeleteModal.vue'; -import DropdownItem from 'shared/components/ui/dropdown/DropdownItem'; -import DropdownMenu from 'shared/components/ui/dropdown/DropdownMenu'; -import FeatureToggle from './widgets/FeatureToggle'; +import DropdownItem from 'shared/components/ui/dropdown/DropdownItem.vue'; +import DropdownMenu from 'shared/components/ui/dropdown/DropdownMenu.vue'; +import FeatureToggle from './widgets/FeatureToggle.vue'; import HorizontalBar from './widgets/chart/HorizontalBarChart'; import Input from './widgets/forms/Input.vue'; import PhoneInput from './widgets/forms/PhoneInput.vue'; -import Label from './ui/Label'; -import LoadingState from './widgets/LoadingState'; -import Modal from './Modal'; -import ModalHeader from './ModalHeader'; -import ReportStatsCard from './widgets/ReportStatsCard'; -import SidemenuIcon from './SidemenuIcon'; -import Spinner from 'shared/components/Spinner'; -import SubmitButton from './buttons/FormSubmitButton'; -import Tabs from './ui/Tabs/Tabs'; -import TabsItem from './ui/Tabs/TabsItem'; +import Label from './ui/Label.vue'; +import LoadingState from './widgets/LoadingState.vue'; +import Modal from './Modal.vue'; +import ModalHeader from './ModalHeader.vue'; +import ReportStatsCard from './widgets/ReportStatsCard.vue'; +import SidemenuIcon from './SidemenuIcon.vue'; +import Spinner from 'shared/components/Spinner.vue'; +import SubmitButton from './buttons/FormSubmitButton.vue'; +import Tabs from './ui/Tabs/Tabs.jsx'; +import TabsItem from './ui/Tabs/TabsItem.vue'; import Thumbnail from './widgets/Thumbnail.vue'; const WootUIKit = { diff --git a/app/javascript/dashboard/components/ui/Tabs/Tabs.js b/app/javascript/dashboard/components/ui/Tabs/Tabs.jsx similarity index 100% rename from app/javascript/dashboard/components/ui/Tabs/Tabs.js rename to app/javascript/dashboard/components/ui/Tabs/Tabs.jsx diff --git a/app/javascript/dashboard/components/widgets/ColorPicker.vue b/app/javascript/dashboard/components/widgets/ColorPicker.vue index 8e8ac89b5..b5a497173 100644 --- a/app/javascript/dashboard/components/widgets/ColorPicker.vue +++ b/app/javascript/dashboard/components/widgets/ColorPicker.vue @@ -53,8 +53,8 @@ export default {