diff --git a/Gemfile b/Gemfile index 001874ad6e..8b4199364c 100644 --- a/Gemfile +++ b/Gemfile @@ -4,7 +4,7 @@ git_source(:github) { |repo| "https://github.com/#{repo}.git" } ruby '~> 3.1.2' # Bundle edge Rails instead: gem 'rails', github: 'rails/rails' -gem 'rails', '~> 7.1.3' +gem 'rails', '~> 7.2.1' # Use mysql as the database for Active Record gem 'mysql2', '~> 0.5.6' # Use Puma as the app server diff --git a/Gemfile.lock b/Gemfile.lock index 1649666078..b2dffa584e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,80 +1,76 @@ GEM remote: https://rubygems.org/ specs: - actioncable (7.1.3.4) - actionpack (= 7.1.3.4) - activesupport (= 7.1.3.4) + actioncable (7.2.1) + actionpack (= 7.2.1) + activesupport (= 7.2.1) nio4r (~> 2.0) websocket-driver (>= 0.6.1) zeitwerk (~> 2.6) - actionmailbox (7.1.3.4) - actionpack (= 7.1.3.4) - activejob (= 7.1.3.4) - activerecord (= 7.1.3.4) - activestorage (= 7.1.3.4) - activesupport (= 7.1.3.4) - mail (>= 2.7.1) - net-imap - net-pop - net-smtp - actionmailer (7.1.3.4) - actionpack (= 7.1.3.4) - actionview (= 7.1.3.4) - activejob (= 7.1.3.4) - activesupport (= 7.1.3.4) - mail (~> 2.5, >= 2.5.4) - net-imap - net-pop - net-smtp + actionmailbox (7.2.1) + actionpack (= 7.2.1) + activejob (= 7.2.1) + activerecord (= 7.2.1) + activestorage (= 7.2.1) + activesupport (= 7.2.1) + mail (>= 2.8.0) + actionmailer (7.2.1) + actionpack (= 7.2.1) + actionview (= 7.2.1) + activejob (= 7.2.1) + activesupport (= 7.2.1) + mail (>= 2.8.0) rails-dom-testing (~> 2.2) - actionpack (7.1.3.4) - actionview (= 7.1.3.4) - activesupport (= 7.1.3.4) + actionpack (7.2.1) + actionview (= 7.2.1) + activesupport (= 7.2.1) nokogiri (>= 1.8.5) racc - rack (>= 2.2.4) + rack (>= 2.2.4, < 3.2) rack-session (>= 1.0.1) rack-test (>= 0.6.3) rails-dom-testing (~> 2.2) rails-html-sanitizer (~> 1.6) - actiontext (7.1.3.4) - actionpack (= 7.1.3.4) - activerecord (= 7.1.3.4) - activestorage (= 7.1.3.4) - activesupport (= 7.1.3.4) + useragent (~> 0.16) + actiontext (7.2.1) + actionpack (= 7.2.1) + activerecord (= 7.2.1) + activestorage (= 7.2.1) + activesupport (= 7.2.1) globalid (>= 0.6.0) nokogiri (>= 1.8.5) - actionview (7.1.3.4) - activesupport (= 7.1.3.4) + actionview (7.2.1) + activesupport (= 7.2.1) builder (~> 3.1) erubi (~> 1.11) rails-dom-testing (~> 2.2) rails-html-sanitizer (~> 1.6) - activejob (7.1.3.4) - activesupport (= 7.1.3.4) + activejob (7.2.1) + activesupport (= 7.2.1) globalid (>= 0.3.6) - activemodel (7.1.3.4) - activesupport (= 7.1.3.4) - activerecord (7.1.3.4) - activemodel (= 7.1.3.4) - activesupport (= 7.1.3.4) + activemodel (7.2.1) + activesupport (= 7.2.1) + activerecord (7.2.1) + activemodel (= 7.2.1) + activesupport (= 7.2.1) timeout (>= 0.4.0) - activestorage (7.1.3.4) - actionpack (= 7.1.3.4) - activejob (= 7.1.3.4) - activerecord (= 7.1.3.4) - activesupport (= 7.1.3.4) + activestorage (7.2.1) + actionpack (= 7.2.1) + activejob (= 7.2.1) + activerecord (= 7.2.1) + activesupport (= 7.2.1) marcel (~> 1.0) - activesupport (7.1.3.4) + activesupport (7.2.1) base64 bigdecimal - concurrent-ruby (~> 1.0, >= 1.0.2) + concurrent-ruby (~> 1.0, >= 1.3.1) connection_pool (>= 2.2.5) drb i18n (>= 1.6, < 2) + logger (>= 1.4.2) minitest (>= 5.1) - mutex_m - tzinfo (~> 2.0) + securerandom (>= 0.3) + tzinfo (~> 2.0, >= 2.0.5) addressable (2.8.6) public_suffix (>= 2.0.2, < 6.0) aes_key_wrap (1.1.0) @@ -297,7 +293,6 @@ GEM bigdecimal (~> 3.1) mustermann (3.0.0) ruby2_keywords (~> 0.0.1) - mutex_m (0.2.0) mysql2 (0.5.6) net-http (0.4.1) uri @@ -396,20 +391,20 @@ GEM rackup (1.0.0) rack (< 3) webrick - rails (7.1.3.4) - actioncable (= 7.1.3.4) - actionmailbox (= 7.1.3.4) - actionmailer (= 7.1.3.4) - actionpack (= 7.1.3.4) - actiontext (= 7.1.3.4) - actionview (= 7.1.3.4) - activejob (= 7.1.3.4) - activemodel (= 7.1.3.4) - activerecord (= 7.1.3.4) - activestorage (= 7.1.3.4) - activesupport (= 7.1.3.4) + rails (7.2.1) + actioncable (= 7.2.1) + actionmailbox (= 7.2.1) + actionmailer (= 7.2.1) + actionpack (= 7.2.1) + actiontext (= 7.2.1) + actionview (= 7.2.1) + activejob (= 7.2.1) + activemodel (= 7.2.1) + activerecord (= 7.2.1) + activestorage (= 7.2.1) + activesupport (= 7.2.1) bundler (>= 1.15.0) - railties (= 7.1.3.4) + railties (= 7.2.1) rails-controller-testing (1.0.5) actionpack (>= 5.0.1.rc1) actionview (>= 5.0.1.rc1) @@ -424,10 +419,10 @@ GEM rails-i18n (7.0.9) i18n (>= 0.7, < 2) railties (>= 6.0.0, < 8) - railties (7.1.3.4) - actionpack (= 7.1.3.4) - activesupport (= 7.1.3.4) - irb + railties (7.2.1) + actionpack (= 7.2.1) + activesupport (= 7.2.1) + irb (~> 1.13) rackup (>= 1.0.0) rake (>= 12.2) thor (~> 1.0, >= 1.2.2) @@ -483,6 +478,7 @@ GEM logger ruby2_keywords (0.0.5) rubyzip (2.3.2) + securerandom (0.3.1) selenium-webdriver (4.23.0) base64 (~> 0.2) logger (~> 1.4) @@ -534,6 +530,7 @@ GEM concurrent-ruby (~> 1.0) unicode-display_width (2.5.0) uri (0.13.0) + useragent (0.16.10) validate_url (1.0.15) activemodel (>= 3.0.0) public_suffix @@ -625,7 +622,7 @@ DEPENDENCIES puma (~> 6.4.2) pundit (~> 2.3.2) rack-mini-profiler (~> 3.3.1) - rails (~> 7.1.3) + rails (~> 7.2.1) rails-controller-testing (~> 1.0.5) rails-i18n (~> 7.0.9) rb-readline (~> 0.5.5) diff --git a/app/assets/stylesheets/components.css.scss b/app/assets/stylesheets/components.css.scss index 83e83dd225..0d744bc19f 100644 --- a/app/assets/stylesheets/components.css.scss +++ b/app/assets/stylesheets/components.css.scss @@ -84,12 +84,12 @@ } .col-form-label { + text-align: right; + font-weight: bold; + @include media-breakpoint-down(sm) { text-align: left; } - - text-align: right; - font-weight: bold; } h1 small, diff --git a/app/assets/stylesheets/components/action-card.css.scss b/app/assets/stylesheets/components/action-card.css.scss index a2659c8dbb..2fd28033cf 100644 --- a/app/assets/stylesheets/components/action-card.css.scss +++ b/app/assets/stylesheets/components/action-card.css.scss @@ -7,25 +7,8 @@ border-color 145ms ease, background-color 145ms ease; box-shadow: none; - - .card-subtitle { - margin-bottom: 0.125rem; - height: 48px; - - h4 { - width: 100%; - line-height: 20px; - min-height: 24px; - - small { - font-size: 65%; - } - } - - .card-title-icon { - margin-right: 1rem; - } - } + background: var(--clickable-card-color); + color: var(--on-clickable-card-color); --clickable-card-color: var(--d-primary); --on-clickable-card-color: var(--d-on-primary); @@ -40,9 +23,6 @@ --on-clickable-card-color: var(--d-on-success); } - background: var(--clickable-card-color); - color: var(--on-clickable-card-color); - small { color: var(--on-clickable-card-color); } @@ -72,4 +52,23 @@ opacity: 0.38; pointer-events: none; } + + .card-subtitle { + margin-bottom: 0.125rem; + height: 48px; + + h4 { + width: 100%; + line-height: 20px; + min-height: 24px; + + small { + font-size: 65%; + } + } + + .card-title-icon { + margin-right: 1rem; + } + } } diff --git a/app/assets/stylesheets/components/btn.css.scss b/app/assets/stylesheets/components/btn.css.scss index d6f211550e..850cfce89a 100644 --- a/app/assets/stylesheets/components/btn.css.scss +++ b/app/assets/stylesheets/components/btn.css.scss @@ -12,6 +12,12 @@ border-color 145ms ease, background-color 145ms ease; + // define the default button colors + // makes it easier to combine with other classes such as d-btn-danger, d-btn-success, etc. + --d-btn-color: var(--d-primary); + --d-btn-color-rgb: var(--d-primary-rgb); + --d-on-btn-color: var(--d-on-primary); + &.with-icon { padding-left: 16px; padding-right: 24px; @@ -50,12 +56,6 @@ pointer-events: auto; cursor: default; } - - // define the default button colors - // makes it easier to combine with other classes such as d-btn-danger, d-btn-success, etc. - --d-btn-color: var(--d-primary); - --d-btn-color-rgb: var(--d-primary-rgb); - --d-on-btn-color: var(--d-on-primary); } .btn.btn-filled, diff --git a/app/assets/stylesheets/components/code_listing.css.scss b/app/assets/stylesheets/components/code_listing.css.scss index aa63b57535..effd2e5fd7 100644 --- a/app/assets/stylesheets/components/code_listing.css.scss +++ b/app/assets/stylesheets/components/code_listing.css.scss @@ -373,11 +373,11 @@ /* stylelint-enable selector-class-pattern */ .annotation-meta-icon { + margin-left: 4px; + &::before { vertical-align: bottom; } - - margin-left: 4px; } .annotation-warning::before { diff --git a/app/assets/stylesheets/components/stepper.css.scss b/app/assets/stylesheets/components/stepper.css.scss index 321cf7b357..1cdd531b4f 100644 --- a/app/assets/stylesheets/components/stepper.css.scss +++ b/app/assets/stylesheets/components/stepper.css.scss @@ -51,15 +51,14 @@ @include shadow-z2; background-color: var(--d-surface); + border: none; + border-radius: var(--d-border-radius-base); + padding: 0; @include media-breakpoint-up(sm) { margin-left: 45px; } - border: none; - border-radius: var(--d-border-radius-base); - padding: 0; - &.panel-body-transparent { background-color: transparent; diff --git a/app/assets/stylesheets/layout/navbar.css.scss b/app/assets/stylesheets/layout/navbar.css.scss index 99e7cb2e15..4cf36955a2 100644 --- a/app/assets/stylesheets/layout/navbar.css.scss +++ b/app/assets/stylesheets/layout/navbar.css.scss @@ -97,15 +97,15 @@ // Drawer toggle & brand link .drawer-toggle { - i { - line-height: var(--d-navbar-height); - font-size: 24px; - } - border: none; outline: none; background: none; color: var(--d-on-primary); + + i { + line-height: var(--d-navbar-height); + font-size: 24px; + } } .brand { @@ -305,10 +305,6 @@ } .dodona-navbar-toggle { - @include media-breakpoint-up(md) { - display: none; - } - position: absolute; top: 0; right: 10px; @@ -316,6 +312,10 @@ background: none; color: var(--d-on-primary); + @include media-breakpoint-up(md) { + display: none; + } + i { line-height: var(--d-navbar-height); } @@ -363,19 +363,18 @@ } .dropdown-title { + display: inline-block; + transform: translateY(-0.5em); + @include media-breakpoint-up(md) { @include media-breakpoint-down(lg) { display: none; } } - display: inline-block; - @include media-breakpoint-down(md) { padding-left: 25px; } - - transform: translateY(-0.5em); } } diff --git a/app/assets/stylesheets/models/questions.css.scss b/app/assets/stylesheets/models/questions.css.scss index 84a5522385..5648fa0ae9 100644 --- a/app/assets/stylesheets/models/questions.css.scss +++ b/app/assets/stylesheets/models/questions.css.scss @@ -1,4 +1,6 @@ .question-table { + table-layout: fixed; + col.actions { width: 50px; } @@ -22,8 +24,6 @@ background-color: var(--d-table-hover-bg); } } - - table-layout: fixed; } @include media-breakpoint-up(md) { diff --git a/app/assets/stylesheets/theme/m3-theme-dark.css.scss b/app/assets/stylesheets/theme/m3-theme-dark.css.scss index 5a2cbc7a44..6bf1e1241e 100644 --- a/app/assets/stylesheets/theme/m3-theme-dark.css.scss +++ b/app/assets/stylesheets/theme/m3-theme-dark.css.scss @@ -198,6 +198,19 @@ --d-code-bg: #{$neutral-30}; --d-skeleton-color: var(--d-surface-variant); + // annotations + --d-annotation-question-background: #{color.mix($purple-80, $neutral-25, 8%)}; + --d-annotation-user-background: #{color.mix($success-70, $neutral-25, 8%)}; + --d-annotation-question-background-intense: #{color.mix($purple-80, $neutral-25, 20%)}; + --d-annotation-user-background-intense: #{color.mix($success-70, $neutral-25, 20%)}; + + @include wavy-underline(--d-annotation-warning-background, $warning-80, 0.7); + @include wavy-underline(--d-annotation-warning-background-intense, $warning-80, 1.7); + @include wavy-underline(--d-annotation-error-background, $danger-70, 0.7); + @include wavy-underline(--d-annotation-error-background-intense, $danger-70, 1.7); + @include wavy-underline(--d-annotation-info-background, $info-80, 0.7); + @include wavy-underline(--d-annotation-info-background-intense, $info-80, 1.7); + .light-only { display: none; } @@ -214,19 +227,6 @@ color-scheme: dark; } - // annotations - --d-annotation-question-background: #{color.mix($purple-80, $neutral-25, 8%)}; - --d-annotation-user-background: #{color.mix($success-70, $neutral-25, 8%)}; - --d-annotation-question-background-intense: #{color.mix($purple-80, $neutral-25, 20%)}; - --d-annotation-user-background-intense: #{color.mix($success-70, $neutral-25, 20%)}; - - @include wavy-underline(--d-annotation-warning-background, $warning-80, 0.7); - @include wavy-underline(--d-annotation-warning-background-intense, $warning-80, 1.7); - @include wavy-underline(--d-annotation-error-background, $danger-70, 0.7); - @include wavy-underline(--d-annotation-error-background-intense, $danger-70, 1.7); - @include wavy-underline(--d-annotation-info-background, $info-80, 0.7); - @include wavy-underline(--d-annotation-info-background-intense, $info-80, 1.7); - .image-bright { // $gray-90 converted to filter using https://codepen.io/sosuke/pen/Pjoqqp filter: invert(86%) sepia(3%) saturate(218%) hue-rotate(242deg) brightness(107%) contrast(90%); diff --git a/app/assets/stylesheets/theme/m3-theme-light.css.scss b/app/assets/stylesheets/theme/m3-theme-light.css.scss index 64da055ae9..9546d71ae3 100644 --- a/app/assets/stylesheets/theme/m3-theme-light.css.scss +++ b/app/assets/stylesheets/theme/m3-theme-light.css.scss @@ -201,19 +201,6 @@ --d-code-bg: #{$neutral-95}; --d-skeleton-color: var(--d-surface-variant); - // this should be fixed using css and not in scss - .dark-only { - display: none; - } - - .light-only { - display: unset; - } - - :root { - color-scheme: light; - } - // font --d-font-monospace: sfmono-regular, menlo, monaco, consolas, "Liberation Mono", "Courier New", monospace; --d-font-sans-serif: roboto, "Helvetica Neue", helvetica, arial, sans-serif; @@ -238,6 +225,19 @@ @include wavy-underline(--d-annotation-info-background, $info-40, 0.7); @include wavy-underline(--d-annotation-info-background-intense, $info-40, 1.7); + // this should be fixed using css and not in scss + .dark-only { + display: none; + } + + .light-only { + display: unset; + } + + :root { + color-scheme: light; + } + .image-bright { // $gray-10 converted to filter using https://codepen.io/sosuke/pen/Pjoqqp filter: invert(8%) sepia(10%) saturate(679%) hue-rotate(201deg) brightness(93%) contrast(92%); diff --git a/bin/rubocop b/bin/rubocop new file mode 100755 index 0000000000..40330c0ff1 --- /dev/null +++ b/bin/rubocop @@ -0,0 +1,8 @@ +#!/usr/bin/env ruby +require "rubygems" +require "bundler/setup" + +# explicit rubocop config increases performance slightly while avoiding config confusion. +ARGV.unshift("--config", File.expand_path("../.rubocop.yml", __dir__)) + +load Gem.bin_path("rubocop", "rubocop") diff --git a/config/application.rb b/config/application.rb index 9725f17717..5cd9e6800a 100644 --- a/config/application.rb +++ b/config/application.rb @@ -9,9 +9,15 @@ module Dodona class Application < Rails::Application # Initialize configuration defaults for originally generated Rails version. - config.load_defaults 7.1 + config.load_defaults 7.2 config.dodona_email = 'dodona@ugent.be' + + # Please, add to the `ignore` list any other `lib` subdirectories that do + # not contain `.rb` files, or that should not be reloaded or eager loaded. + # Common ones are `templates`, `generators`, or `middleware`, for example. + config.autoload_lib(ignore: %w[assets tasks]) + # Configuration for the application, engines, and railties goes here. # # These settings can be overridden in specific environments using the files diff --git a/config/environments/test.rb b/config/environments/test.rb index a917e1bf28..60cd71ea3f 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -77,4 +77,6 @@ routes.default_url_options[:trailing_slash] = true routes.default_url_options[:locale] = 'en' + + config.active_job.queue_adapter = :test end diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb index 6544844273..092cf6cd94 100644 --- a/config/initializers/assets.rb +++ b/config/initializers/assets.rb @@ -1,7 +1,7 @@ # Be sure to restart your server when you modify this file. # Version of your assets, change this if you want to expire all your assets. -Rails.application.config.assets.version = '1.0' +Rails.application.config.assets.version = "1.0" # Add additional assets to the asset load path. # Rails.application.config.assets.paths << Emoji.images_path @@ -11,7 +11,7 @@ # Precompile additional assets. # application.js, application.css, and all non-JS/CSS in the app/assets # folder are already added. -# Rails.application.config.assets.precompile += %w( admin.js admin.css ) +# Rails.application.config.assets.precompile += %w[ admin.js admin.css ] # These files are fetched from within other js assets # so they do not support rails sprockets renaming them diff --git a/config/initializers/filter_parameter_logging.rb b/config/initializers/filter_parameter_logging.rb index 4b34a03668..c010b83ddd 100644 --- a/config/initializers/filter_parameter_logging.rb +++ b/config/initializers/filter_parameter_logging.rb @@ -1,6 +1,8 @@ # Be sure to restart your server when you modify this file. -# Configure sensitive parameters which will be filtered from the log file. +# Configure parameters to be partially matched (e.g. passw matches password) and filtered from the log file. +# Use this to limit dissemination of sensitive information. +# See the ActiveSupport::ParameterFilter documentation for supported notations and behaviors. Rails.application.config.filter_parameters += [ - :passw, :secret, :token, :_key, :crypt, :salt, :certificate, :otp, :ssn + :passw, :email, :secret, :token, :_key, :crypt, :salt, :certificate, :otp, :ssn ] diff --git a/config/initializers/permissions_policy.rb b/config/initializers/permissions_policy.rb index 00f64d71b0..7db3b9577e 100644 --- a/config/initializers/permissions_policy.rb +++ b/config/initializers/permissions_policy.rb @@ -1,11 +1,13 @@ +# Be sure to restart your server when you modify this file. + # Define an application-wide HTTP permissions policy. For further -# information see https://developers.google.com/web/updates/2018/06/feature-policy -# -# Rails.application.config.permissions_policy do |f| -# f.camera :none -# f.gyroscope :none -# f.microphone :none -# f.usb :none -# f.fullscreen :self -# f.payment :self, "https://secure.example.com" +# information see: https://developers.google.com/web/updates/2018/06/feature-policy + +# Rails.application.config.permissions_policy do |policy| +# policy.camera :none +# policy.gyroscope :none +# policy.microphone :none +# policy.usb :none +# policy.fullscreen :self +# policy.payment :self, "https://secure.example.com" # end diff --git a/config/puma.rb b/config/puma.rb index d9b3e836cf..200834bb9a 100644 --- a/config/puma.rb +++ b/config/puma.rb @@ -1,12 +1,23 @@ -# Puma can serve each request in a thread from an internal thread pool. -# The `threads` method setting takes two numbers: a minimum and maximum. -# Any libraries that use thread pools should be configured to match -# the maximum value specified for Puma. Default is set to 5 threads for minimum -# and maximum; this matches the default thread size of Active Record. +# Puma starts a configurable number of processes (workers) and each process +# serves each request in a thread from an internal thread pool. # -max_threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 } -min_threads_count = ENV.fetch("RAILS_MIN_THREADS") { max_threads_count } -threads min_threads_count, max_threads_count +# The ideal number of threads per worker depends both on how much time the +# application spends waiting for IO operations and on how much you wish to +# to prioritize throughput over latency. +# +# As a rule of thumb, increasing the number of threads will increase how much +# traffic a given process can handle (throughput), but due to CRuby's +# Global VM Lock (GVL) it has diminishing returns and will degrade the +# response time (latency) of the application. +# +# The default is set to 3 threads as it's deemed a decent compromise between +# throughput and latency for the average Rails application. +# +# Any libraries that use a connection pool or another resource pool should +# be configured to provide at least as many connections as the number of +# threads. This includes Active Record's `pool` parameter in `database.yml`. +threads_count = ENV.fetch("RAILS_MAX_THREADS", 3) +threads threads_count, threads_count # Specifies the `worker_timeout` threshold that Puma will use to wait before # terminating a worker in development environments. @@ -15,29 +26,15 @@ # Specifies the `port` that Puma will listen on to receive requests; default is 3000. # -port ENV.fetch("PORT") { 3000 } +port ENV.fetch("PORT", 3000) # Specifies the `environment` that Puma will run in. # -environment ENV.fetch("RAILS_ENV") { "development" } - -# Specifies the `pidfile` that Puma will use. -pidfile ENV.fetch("PIDFILE") { "tmp/pids/server.pid" } - -# Specifies the number of `workers` to boot in clustered mode. -# Workers are forked web server processes. If using threads and workers together -# the concurrency of the application would be max `threads` * `workers`. -# Workers do not work on JRuby or Windows (both of which do not support -# processes). -# -# workers ENV.fetch("WEB_CONCURRENCY") { 2 } - -# Use the `preload_app!` method when specifying a `workers` number. -# This directive tells Puma to first boot the application and load code -# before forking the application. This takes advantage of Copy On Write -# process behavior so workers use less memory. -# -# preload_app! +environment ENV.fetch("RAILS_ENV", "development") # Allow puma to be restarted by `rails restart` command. plugin :tmp_restart + +# Specifies the `pidfile` that Puma will use. +pidfile ENV.fetch("PIDFILE", "tmp/pids/server.pid") + diff --git a/public/404.html b/public/404.html index b612547fc2..2be3af26fc 100644 --- a/public/404.html +++ b/public/404.html @@ -4,7 +4,7 @@
Please upgrade your browser to continue.
+