diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml index 32997e0..1cea344 100644 --- a/.devcontainer/docker-compose.yml +++ b/.devcontainer/docker-compose.yml @@ -2,5 +2,8 @@ version: '3.8' services: # Update this to the name of the service you want to work with in your docker-compose.yml file app: + environment: + EDITOR: code + SHELL: fish command: /bin/sh -c "while sleep 1000; do :; done" diff --git a/.dockerignore b/.dockerignore index 066cd7a..36170e5 100644 --- a/.dockerignore +++ b/.dockerignore @@ -39,4 +39,5 @@ /Dockerfile /docker-compose.yml -/.forgejo/ \ No newline at end of file +/.forgejo/ +/core* diff --git a/.forgejo/workflows/ci_cd.yml b/.forgejo/workflows/ci_cd.yml index 0f17daa..b43fc55 100644 --- a/.forgejo/workflows/ci_cd.yml +++ b/.forgejo/workflows/ci_cd.yml @@ -66,7 +66,7 @@ jobs: path: repository key: ${{ runner.os }}-repository-${{ github.sha }} restore-keys: | - ${{ runner.os }}-repository- + ${{ runner.os }}-repository - name: Checkout repository uses: actions/checkout@v4 with: diff --git a/.github/dependabot.yml b/.github/dependabot.yml deleted file mode 100644 index f33a02c..0000000 --- a/.github/dependabot.yml +++ /dev/null @@ -1,12 +0,0 @@ -# To get started with Dependabot version updates, you'll need to specify which -# package ecosystems to update and where the package manifests are located. -# Please see the documentation for more information: -# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates -# https://containers.dev/guide/dependabot - -version: 2 -updates: - - package-ecosystem: "devcontainers" - directory: "/" - schedule: - interval: weekly diff --git a/.rubocop.yml b/.rubocop.yml index 25b6323..466c8dd 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,3 +1,6 @@ +inherit_gem: + rubocop-rails-omakase: rubocop.yml + require: - rubocop-capybara - rubocop-rails diff --git a/.vscode/launch.json b/.vscode/launch.json index dda0271..a2f99f9 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -10,18 +10,5 @@ "request": "attach", "preLaunchTask": "dev" }, - { - "type": "ruby_lsp", - "name": "Debug script", - "request": "launch", - "program": "ruby ${file}" - }, - { - "type": "ruby_lsp", - "name": "Debug test", - "request": "launch", - "program": "ruby -Itest ${relativeFile}" - }, - ] } \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 2b3522d..1f77ccb 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -2,10 +2,21 @@ "version": "2.0.0", "tasks": [ { - "type": "shell", + "type": "process", + "presentation": { + "echo": true, + "reveal": "silent", + "focus": false, + "panel": "dedicated", + "showReuseMessage": true, + "clear": false, + "revealProblems": "always", + "group": "dev", + "close": true + }, "command": "dev", "label": "dev", - "isBackground": true + "isBackground": true, } ] } \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 9f587ba..949012b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -47,7 +47,7 @@ RUN \ echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && \ apt-get update -yqq && \ apt-get install -yqq --no-install-recommends \ - sqlite3 nodejs npm sassc yarn libvips fish ranger pandoc && \ + sqlite3 nodejs npm sassc yarn libvips fish ranger pandoc libjemalloc2 && \ apt-get clean && \ npm install tabby-agent && \ rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* && \ @@ -55,26 +55,23 @@ RUN \ gem update --system && \ bundle config set app_config ${GEM_HOME} +ENV LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.2 + USER ${NAME} -FROM development AS builder +RUN mkdir -p ~/.config/fish && echo "set fish_greeting" >> ~/.config/fish/config.fish +RUN \ + echo >> ~/.config/fish/config.fish &&\ + echo "function fish_prompt" >> ~/.config/fish/config.fish &&\ + echo " set -l last_status \$status" >> ~/.config/fish/config.fish &&\ + echo " set -l stat" >> ~/.config/fish/config.fish &&\ + echo " if test \$last_status -ne 0" >> ~/.config/fish/config.fish &&\ + echo " set stat (set_color red)\"[\$last_status]\"(set_color normal)" >> ~/.config/fish/config.fish &&\ + echo " end" >> ~/.config/fish/config.fish &&\ + echo " string join '' -- (set_color green) (prompt_pwd) (set_color normal) \$stat ' 🐳 '" >> ~/.config/fish/config.fish && \ + echo "end" >> ~/.config/fish/config.fish -USER root - -COPY Gemfile Gemfile.lock package.json yarn.lock ./ - -RUN bundle install && yarn install - -FROM builder AS assets - -COPY . . - -COPY --from=builder /app/.bundle /app/.bundle -COPY --from=builder /app/node_modules /app/node_modules - -RUN RAILS_ENV=production SECRET_KEY_BASE_DUMMY=1 rails assets:precompile - -FROM ruby:${RUBY_VERSION}-slim AS production +FROM ruby:${RUBY_VERSION}-alpine AS builder ARG NAME ARG UID @@ -84,50 +81,111 @@ ARG INSTALL_DIR WORKDIR ${INSTALL_DIR} +ENV GEM_HOME=${INSTALL_DIR}/.bundle + ENV \ LANG=C.UTF-8 \ INSTALL_DIR=${INSTALL_DIR} \ - RAILS_ENV=production \ + RAILS_ENV=development \ TZ=Europe/Zurich \ - PATH=${INSTALL_DIR}/bin:$GEM_HOME/bin:$GEM_HOME/gems/bin:$PATH + PATH=${INSTALL_DIR}/bin:$GEM_HOME/bin:$GEM_HOME/gems/bin:$PATH \ + EDITOR=vim -ENV GEM_HOME=${INSTALL_DIR}/.bundle - -RUN \ - ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && \ - echo $TZ > /etc/timezone && \ - addgroup --gid ${GID} ${NAME} && \ - adduser \ - --gecos GECOS \ - --home /home/${NAME} \ - --uid ${UID} \ - --gid ${GID} \ - --disabled-password \ - --disabled-login \ - --shell /bin/bash \ - ${NAME} && \ - apt-get update -yqq && \ - apt-get install -yqq --no-install-recommends \ - sqlite3 libvips pandoc && \ - apt-get clean && \ - rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* && \ +RUN apk add --update --no-cache \ + binutils-gold \ + build-base \ + curl \ + file \ + g++ \ + gcc \ + git \ + less \ + libstdc++ \ + libffi-dev \ + libc-dev \ + linux-headers \ + libxml2-dev \ + libxslt-dev \ + libgcrypt-dev \ + make \ + netcat-openbsd \ + nodejs \ + openssl \ + pkgconfig \ + tzdata \ + yarn \ + sqlite \ + vips-dev \ + npm \ + sassc \ + jemalloc \ + pandoc-cli \ + sqlite-libs \ + build-base && \ truncate -s 0 /var/log/*log && \ gem update --system && \ bundle config set app_config ${GEM_HOME} -EXPOSE 3000 +ENV LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.2 -ENTRYPOINT [ "bin/entrypoint" ] +USER ${NAME} + +USER root + +COPY Gemfile Gemfile.lock package.json yarn.lock ./ + +RUN bundle config without test development && bundle install && yarn install + +FROM builder AS assets COPY . . -COPY --from=builder /app/.bundle /app/.bundle -COPY --from=assets /app/public/assets /app/public/assets +COPY --from=builder ${INSTALL_DIR}/.bundle ${INSTALL_DIR}/.bundle +COPY --from=builder ${INSTALL_DIR}/node_modules ${INSTALL_DIR}/node_modules -RUN chown -R app:app /app/tmp /app/log /app/storage -RUN date +"%Y-%m-%d %H:%M:%S %Z" >> .build_version +RUN RAILS_ENV=production SECRET_KEY_BASE_DUMMY=1 rails assets:precompile + +FROM ruby:${RUBY_VERSION}-alpine AS production + +ARG INSTALL_DIR +ARG NAME + +WORKDIR ${INSTALL_DIR} + +ENV GEM_HOME=${INSTALL_DIR}/.bundle + +ENV \ + RAILS_ENV=production \ + PATH=${INSTALL_DIR}/bin:$GEM_HOME/bin:$GEM_HOME/gems/bin:$PATH \ + TZ=Europe/Zurich + +RUN \ + adduser ${NAME} --disabled-password --shell /bin/ash && \ + apk add --update --no-cache \ + tzdata \ + sqlite \ + vips-dev \ + jemalloc && \ + gem update --system && \ + bundle config set app_config ${GEM_HOME} && \ + bundle config set without development test && \ + apk add patchelf && \ + patchelf --add-needed libjemalloc.so.2 /usr/local/bin/ruby && \ + apk del patchelf && \ + truncate -s 0 /var/log/*log + +EXPOSE 3000 + +COPY . . + +COPY --from=builder ${INSTALL_DIR}/.bundle ${INSTALL_DIR}/.bundle +COPY --from=assets ${INSTALL_DIR}/public/assets ${INSTALL_DIR}/public/assets + +RUN chown -R ${NAME}:${NAME} ${INSTALL_DIR}/tmp ${INSTALL_DIR}/log ${INSTALL_DIR}/storage && \ + date +"%Y-%m-%d %H:%M:%S %Z" >> .build_version + +USER ${NAME} + +ENTRYPOINT [ "bin/entrypoint" ] -USER app -# Using variables in command list is not possible: -# https://stackoverflow.com/questions/40454470/how-can-i-use-a-variable-inside-a-dockerfile-cmd CMD [ "rails", "server", "--binding", "0.0.0.0", "--no-daemon", "--port" , "3000" ] diff --git a/Gemfile b/Gemfile index 95e2e4e..fd56b94 100644 --- a/Gemfile +++ b/Gemfile @@ -1,35 +1,36 @@ # frozen_string_literal: true -source 'https://rubygems.org' +source "https://rubygems.org" -ruby '3.3.4' +ruby "3.3.4" # Bundle edge Rails instead: gem "rails", github: "rails/rails", branch: "main" -gem 'rails', '~> 7.1.3', '>= 7.1.3.4' +gem "rails", "~> 7.2" # The original asset pipeline for Rails [https://github.com/rails/sprockets-rails] -gem 'sprockets-rails' +gem "sprockets-rails" # Use sqlite3 as the database for Active Record -gem 'sqlite3', '~> 1.4' +# gem "sqlite3", "~> 1.4" +gem "sqlite3", ">= 2.0" # Use the Puma web server [https://github.com/puma/puma] -gem 'puma', '>= 5.0' +gem "puma", ">= 5.0" # Bundle and transpile JavaScript [https://github.com/rails/jsbundling-rails] -gem 'jsbundling-rails' +gem "jsbundling-rails" # Hotwire's SPA-like page accelerator [https://turbo.hotwired.dev] -gem 'turbo-rails' +gem "turbo-rails" # Hotwire's modest JavaScript framework [https://stimulus.hotwired.dev] -gem 'stimulus-rails' +gem "stimulus-rails" # Bundle and process CSS [https://github.com/rails/cssbundling-rails] -gem 'cssbundling-rails' +gem "cssbundling-rails" # Build JSON APIs with ease [https://github.com/rails/jbuilder] -gem 'jbuilder' +gem "jbuilder" # Use Redis adapter to run Action Cable in production # gem "redis", ">= 4.0.1" @@ -41,45 +42,50 @@ gem 'jbuilder' # gem "bcrypt", "~> 3.1.7" # Windows does not include zoneinfo files, so bundle the tzinfo-data gem -gem 'tzinfo-data', platforms: %i[windows jruby] +gem "tzinfo-data", platforms: %i[windows jruby] # Reduces boot times through caching; required in config/boot.rb -gem 'bootsnap', require: false +gem "bootsnap", require: false # Use Active Storage variants [https://guides.rubyonrails.org/active_storage_overview.html#transforming-images] -gem 'bootstrap_form' -gem 'caxlsx' -gem 'caxlsx_rails' -gem 'image_processing', '~> 1.2' -gem 'pagy', '~> 9.0' -gem 'pandoc-ruby' -gem 'prawn-markup' -gem 'prawn-rails' -gem 'sablon' +gem "bootstrap_form" +gem "caxlsx" +gem "caxlsx_rails" +gem "image_processing", "~> 1.2" +gem "openxml-docx" +gem "pagy", "~> 9.0" +gem "pandoc-ruby" +gem "prawn-markup" +gem "prawn-rails" +gem "sablon" +gem "activerecord-enhancedsqlite3-adapter" +gem "slim" group :development, :test do # See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem - gem 'debug', platforms: %i[mri windows] + gem "debug", platforms: %i[mri windows] end group :development do # Use console on exceptions pages [https://github.com/rails/web-console] - gem 'web-console' + gem "web-console" # Add speed badges [https://github.com/MiniProfiler/rack-mini-profiler] # gem "rack-mini-profiler" # Speed up commands on slow machines / big apps [https://github.com/rails/spring] # gem "spring" - gem 'rubocop' - gem 'rubocop-capybara' - gem 'rubocop-rails' - gem 'ruby-lsp' - gem 'ruby-lsp-rails' + gem "brakeman" + gem "rubocop" + gem "rubocop-capybara" + gem "rubocop-rails" + gem "rubocop-rails-omakase", require: false + gem "ruby-lsp" + gem "ruby-lsp-rails" end group :test do # Use system testing [https://guides.rubyonrails.org/testing.html#system-testing] - gem 'capybara' - gem 'selenium-webdriver' + gem "capybara" + gem "selenium-webdriver" end diff --git a/Gemfile.lock b/Gemfile.lock index ee0de82..975d209 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,80 +1,79 @@ GEM remote: https://rubygems.org/ specs: - actioncable (7.1.3.4) - actionpack (= 7.1.3.4) - activesupport (= 7.1.3.4) + actioncable (7.2.0) + actionpack (= 7.2.0) + activesupport (= 7.2.0) 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.0) + actionpack (= 7.2.0) + activejob (= 7.2.0) + activerecord (= 7.2.0) + activestorage (= 7.2.0) + activesupport (= 7.2.0) + mail (>= 2.8.0) + actionmailer (7.2.0) + actionpack (= 7.2.0) + actionview (= 7.2.0) + activejob (= 7.2.0) + activesupport (= 7.2.0) + 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.0) + actionview (= 7.2.0) + activesupport (= 7.2.0) 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.0) + actionpack (= 7.2.0) + activerecord (= 7.2.0) + activestorage (= 7.2.0) + activesupport (= 7.2.0) globalid (>= 0.6.0) nokogiri (>= 1.8.5) - actionview (7.1.3.4) - activesupport (= 7.1.3.4) + actionview (7.2.0) + activesupport (= 7.2.0) 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.0) + activesupport (= 7.2.0) 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.0) + activesupport (= 7.2.0) + activerecord (7.2.0) + activemodel (= 7.2.0) + activesupport (= 7.2.0) 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) + activerecord-enhancedsqlite3-adapter (0.8.0) + activerecord (>= 7.1) + sqlite3 (>= 1.6) + activestorage (7.2.0) + actionpack (= 7.2.0) + activejob (= 7.2.0) + activerecord (= 7.2.0) + activesupport (= 7.2.0) marcel (~> 1.0) - activesupport (7.1.3.4) + activesupport (7.2.0) 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.7) public_suffix (>= 2.0.2, < 7.0) ast (2.4.2) @@ -86,6 +85,8 @@ GEM bootstrap_form (5.4.0) actionpack (>= 6.1) activemodel (>= 6.1) + brakeman (6.1.2) + racc builder (3.3.0) capybara (3.40.0) addressable @@ -155,7 +156,6 @@ GEM mini_mime (1.1.5) minitest (5.24.1) msgpack (1.7.2) - mutex_m (0.2.0) net-imap (0.4.14) date net-protocol @@ -178,6 +178,19 @@ GEM racc (~> 1.4) nokogiri (1.16.6-x86_64-linux) racc (~> 1.4) + openxml-docx (0.11.5) + nokogiri + openxml-drawingml + openxml-package (>= 0.2.2) + ox (~> 2.9) + openxml-drawingml (0.3.1) + nokogiri + openxml-package (~> 0.3.2) + openxml-package (0.3.4) + nokogiri + ox + rubyzip + ox (2.14.18) pagy (9.0.2) pandoc-ruby (2.1.10) parallel (1.25.1) @@ -214,20 +227,20 @@ GEM rackup (2.1.0) rack (>= 3) webrick (~> 1.8) - 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.0) + actioncable (= 7.2.0) + actionmailbox (= 7.2.0) + actionmailer (= 7.2.0) + actionpack (= 7.2.0) + actiontext (= 7.2.0) + actionview (= 7.2.0) + activejob (= 7.2.0) + activemodel (= 7.2.0) + activerecord (= 7.2.0) + activestorage (= 7.2.0) + activesupport (= 7.2.0) bundler (>= 1.15.0) - railties (= 7.1.3.4) + railties (= 7.2.0) rails-dom-testing (2.2.0) activesupport (>= 5.0.0) minitest @@ -235,10 +248,10 @@ GEM rails-html-sanitizer (1.6.0) loofah (~> 2.21) nokogiri (~> 1.14) - railties (7.1.3.4) - actionpack (= 7.1.3.4) - activesupport (= 7.1.3.4) - irb + railties (7.2.0) + actionpack (= 7.2.0) + activesupport (= 7.2.0) + irb (~> 1.13) rackup (>= 1.0.0) rake (>= 12.2) thor (~> 1.0, >= 1.2.2) @@ -252,7 +265,7 @@ GEM regexp_parser (2.9.2) reline (0.5.9) io-console (~> 0.5) - rexml (3.3.1) + rexml (3.3.2) strscan rubocop (1.65.0) json (~> 2.3) @@ -269,11 +282,22 @@ GEM parser (>= 3.3.1.0) rubocop-capybara (2.21.0) rubocop (~> 1.41) + rubocop-minitest (0.35.1) + rubocop (>= 1.61, < 2.0) + rubocop-ast (>= 1.31.1, < 2.0) + rubocop-performance (1.21.1) + rubocop (>= 1.48.1, < 2.0) + rubocop-ast (>= 1.31.1, < 2.0) rubocop-rails (2.25.1) activesupport (>= 4.2.0) rack (>= 1.1) rubocop (>= 1.33.0, < 2.0) rubocop-ast (>= 1.31.1, < 2.0) + rubocop-rails-omakase (1.0.0) + rubocop + rubocop-minitest + rubocop-performance + rubocop-rails ruby-lsp (0.17.7) language_server-protocol (~> 3.17.0) prism (>= 0.29.0, < 0.31) @@ -288,12 +312,16 @@ GEM sablon (0.4.1) nokogiri (>= 1.8.5) rubyzip (>= 1.3.0) - selenium-webdriver (4.22.0) + securerandom (0.3.1) + selenium-webdriver (4.23.0) base64 (~> 0.2) logger (~> 1.4) rexml (~> 3.2, >= 3.2.5) rubyzip (>= 1.2.2, < 3.0) websocket (~> 1.0) + slim (5.2.1) + temple (~> 0.10.0) + tilt (>= 2.1.0) sorbet-runtime (0.5.11481) sprockets (4.2.1) concurrent-ruby (~> 1.0) @@ -302,17 +330,19 @@ GEM actionpack (>= 6.1) activesupport (>= 6.1) sprockets (>= 3.0.0) - sqlite3 (1.7.3-aarch64-linux) - sqlite3 (1.7.3-arm-linux) - sqlite3 (1.7.3-arm64-darwin) - sqlite3 (1.7.3-x86-linux) - sqlite3 (1.7.3-x86_64-darwin) - sqlite3 (1.7.3-x86_64-linux) + sqlite3 (2.0.3-aarch64-linux-gnu) + sqlite3 (2.0.3-arm-linux-gnu) + sqlite3 (2.0.3-arm64-darwin) + sqlite3 (2.0.3-x86-linux-gnu) + sqlite3 (2.0.3-x86_64-darwin) + sqlite3 (2.0.3-x86_64-linux-gnu) stimulus-rails (1.3.3) railties (>= 6.0.0) stringio (3.1.1) strscan (3.1.0) + temple (0.10.3) thor (1.3.1) + tilt (2.4.0) timeout (0.4.1) ttfunk (1.8.0) bigdecimal (~> 3.1) @@ -323,6 +353,7 @@ GEM tzinfo (2.0.6) concurrent-ruby (~> 1.0) unicode-display_width (2.5.0) + useragent (0.16.10) web-console (4.2.1) actionview (>= 6.0.0) activemodel (>= 6.0.0) @@ -346,8 +377,10 @@ PLATFORMS x86_64-linux DEPENDENCIES + activerecord-enhancedsqlite3-adapter bootsnap bootstrap_form + brakeman capybara caxlsx caxlsx_rails @@ -356,21 +389,24 @@ DEPENDENCIES image_processing (~> 1.2) jbuilder jsbundling-rails + openxml-docx pagy (~> 9.0) pandoc-ruby prawn-markup prawn-rails puma (>= 5.0) - rails (~> 7.1.3, >= 7.1.3.4) + rails (~> 7.2) rubocop rubocop-capybara rubocop-rails + rubocop-rails-omakase ruby-lsp ruby-lsp-rails sablon selenium-webdriver + slim sprockets-rails - sqlite3 (~> 1.4) + sqlite3 (>= 2.0) stimulus-rails turbo-rails tzinfo-data diff --git a/app/assets/stylesheets/application.bootstrap.scss b/app/assets/stylesheets/application.bootstrap.scss index 2983d77..727a354 100644 --- a/app/assets/stylesheets/application.bootstrap.scss +++ b/app/assets/stylesheets/application.bootstrap.scss @@ -115,6 +115,4 @@ $enable-rounded: false; overflow-y: auto; } */ - - @import "./layout"; \ No newline at end of file diff --git a/app/controllers/admin/backups_controller.rb b/app/controllers/admin/backups_controller.rb index 65dcf87..6b501e0 100644 --- a/app/controllers/admin/backups_controller.rb +++ b/app/controllers/admin/backups_controller.rb @@ -1,8 +1,10 @@ +# frozen_string_literal: true + module Admin class BackupsController < ApplicationController # GET /admin/backups/1 def show - send_file Backup.db_xlsx, filename: 'backup.xlsx', disposition: :attachment + send_file Backup.db_xlsx, filename: "backup.xlsx", disposition: :attachment end end end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index de00ee8..e99f4ce 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -3,20 +3,24 @@ class ApplicationController < ActionController::Base include Pagy::Backend + # allow_browser versions: :modern + before_action :initialize_navbar private def initialize_navbar - @nav_path = controller_name + return unless request.get? + @navbar_items = [ - { label: 'Dashboard', icon: :speedometer2, path: :root }, - { label: Report.model_name.human(count: 2), icon: :'journal-text', path: :reports }, - { label: Checklist.model_name.human(count: 2), icon: :'list-check', path: :checklists }, - { label: Check.model_name.human(count: 2), icon: :check2, path: :checks }, - { label: Link.model_name.human(count: 2), icon: :link, path: :links }, - { label: LinkCategory.model_name.human(count: 2), icon: :"folder", path: :link_categories } + { label: "Dashboard", icon: :speedometer2, path: :root }, + { label: Report.model_name.human(count: 2), icon: :'journal-text', path: :reports }, + { label: Checklist.model_name.human(count: 2), icon: :'list-check', path: :checklists }, + { label: Check.model_name.human(count: 2), icon: :check2, path: :checks }, + { label: Link.model_name.human(count: 2), icon: :link, path: :links }, + { label: LinkCategory.model_name.human(count: 2), icon: :folder, path: :link_categories } ] - @search_url = nil # root_url + @nav_path = controller_name + @search_url = nil end end diff --git a/app/controllers/benchmarking_controller.rb b/app/controllers/benchmarking_controller.rb new file mode 100644 index 0000000..353fc55 --- /dev/null +++ b/app/controllers/benchmarking_controller.rb @@ -0,0 +1,213 @@ +class BenchmarkingController < ApplicationController + protect_from_forgery with: :null_session + before_action :set_user_update_last_seen_at + + # POST /benchmarking/read_heavy + def read_heavy + act_and_respond( + link_create: 0.1, + link_destroy: 0.1, + link_show: 0.4, + links_index: 0.4, + ) + end + + # POST /benchmarking/write_heavy + def write_heavy + act_and_respond( + link_create: 0.4, + link_destroy: 0.4, + link_show: 0.1, + links_index: 0.1, + ) + end + + # POST /benchmarking/balanced + def balanced + act_and_respond( + link_create: 0.25, + link_destroy: 0.25, + link_show: 0.25, + links_index: 0.25, + ) + end + + def link_create + link = LinkCategory.create!(name: "Benchmark #{request.uuid}", description_html: "
#{format(request:)}
") + redirect_to link + end + + def link_destroy + link = LinkCategory.where("id >= ?", rand(LinkCategory.minimum(:id)..LinkCategory.maximum(:id))).limit(1).first + link.destroy! + redirect_to links_path + end + + def link_show + @link_category = LinkCategory.where("id >= ?", rand(LinkCategory.minimum(:id)..LinkCategory.maximum(:id))).limit(1).first + render "link_categories/show", status: :ok + end + + def links_index + @link_categories = LinkCategory.where("id >= ?", rand(LinkCategory.minimum(:id)..LinkCategory.maximum(:id))).limit(100) + render "link_categories/index", status: :ok + end + + private + + def set_user_update_last_seen_at + # @user = User.where("id >= ?", rand(User.minimum(:id)..User.maximum(:id))).limit(1).first + # @user.update!(last_seen_at: Time.now) + end + + def act_and_respond(actions_with_weighted_distribution) + action = actions_with_weighted_distribution.max_by { |_, weight| rand ** (1.0 / weight) }.first + + send(action) + end + + def format(request:) + request.headers.to_h.slice( + "GATEWAY_INTERFACE", + "HTTP_ACCEPT", + "HTTP_HOST", + "HTTP_USER_AGENT", + "HTTP_VERSION", + "ORIGINAL_FULLPATH", + "ORIGINAL_SCRIPT_NAME", + "PATH_INFO", + "QUERY_STRING", + "REMOTE_ADDR", + "REQUEST_METHOD", + "REQUEST_PATH", + "REQUEST_URI", + "SCRIPT_NAME", + "SERVER_NAME", + "SERVER_PORT", + "SERVER_PROTOCOL", + "SERVER_SOFTWARE", + "action_dispatch.request_id", + "puma.request_body_wait", + ).map { _1.join(": ") }.join("\n") + end +end + +# class BenchmarkingController < ApplicationController +# skip_before_action :verify_authenticity_token +# skip_before_action :ensure_user_authenticated! +# before_action :set_user_update_last_seen_at + +# # POST /benchmarking/read_heavy +# def read_heavy +# act_and_respond( +# link_create: 0.10, +# comment_create: 0.10, +# post_destroy: 0.02, +# comment_destroy: 0.03, +# post_show: 0.25, +# posts_index: 0.25, +# user_show: 0.25, +# ) +# end + +# # POST /benchmarking/write_heavy +# def write_heavy +# act_and_respond( +# link_create: 0.25, +# comment_create: 0.25, +# post_destroy: 0.05, +# comment_destroy: 0.20, +# post_show: 0.05, +# posts_index: 0.15, +# user_show: 0.05, +# ) +# end + +# # POST /benchmarking/balanced +# def balanced +# act_and_respond( +# link_create: 0.17, +# comment_create: 0.17, +# post_destroy: 0.05, +# comment_destroy: 0.11, +# post_show: 0.17, +# posts_index: 0.17, +# user_show: 0.16, +# ) +# end + +# def link_create +# post = Post.create!(user: @user, title: "Post #{request.uuid}", description: format(request:)) +# redirect_to post +# end + +# def comment_create +# post = Post.where("id >= ?", rand(Post.minimum(:id)..Post.maximum(:id))).limit(1).first +# comment = Comment.create!(user: @user, post: post, body: "Comment #{request.uuid}") +# redirect_to comment.post +# end + +# def post_destroy +# post = Post.where("id >= ?", rand(Post.minimum(:id)..Post.maximum(:id))).limit(1).first +# post.destroy! +# redirect_to posts_path +# end + +# def comment_destroy +# comment = Comment.where("id >= ?", rand(Comment.minimum(:id)..Comment.maximum(:id))).limit(1).first +# comment.destroy! +# redirect_to comment.post +# end + +# def post_show +# @post = Post.where("id >= ?", rand(Post.minimum(:id)..Post.maximum(:id))).limit(1).first +# render "posts/show", status: :ok +# end + +# def posts_index +# @posts = Post.where("id >= ?", rand(Post.minimum(:id)..Post.maximum(:id))).limit(100) +# render "posts/index", status: :ok +# end + +# def user_show +# render "users/show", status: :ok +# end + +# private + +# def set_user_update_last_seen_at +# @user = User.where("id >= ?", rand(User.minimum(:id)..User.maximum(:id))).limit(1).first +# @user.update!(last_seen_at: Time.now) +# end + +# def act_and_respond(actions_with_weighted_distribution) +# action = actions_with_weighted_distribution.max_by { |_, weight| rand ** (1.0 / weight) }.first + +# send(action) +# end + +# def format(request:) +# request.headers.to_h.slice( +# "GATEWAY_INTERFACE", +# "HTTP_ACCEPT", +# "HTTP_HOST", +# "HTTP_USER_AGENT", +# "HTTP_VERSION", +# "ORIGINAL_FULLPATH", +# "ORIGINAL_SCRIPT_NAME", +# "PATH_INFO", +# "QUERY_STRING", +# "REMOTE_ADDR", +# "REQUEST_METHOD", +# "REQUEST_PATH", +# "REQUEST_URI", +# "SCRIPT_NAME", +# "SERVER_NAME", +# "SERVER_PORT", +# "SERVER_PROTOCOL", +# "SERVER_SOFTWARE", +# "action_dispatch.request_id", +# "puma.request_body_wait", +# ).map { _1.join(": ") }.join("\n") +# end +# end diff --git a/app/controllers/checklist_entries_controller.rb b/app/controllers/checklist_entries_controller.rb index c0f7de4..10ac787 100644 --- a/app/controllers/checklist_entries_controller.rb +++ b/app/controllers/checklist_entries_controller.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class ChecklistEntriesController < ApplicationController before_action :set_checklist_entry, only: %i[show edit update destroy] @@ -7,8 +9,7 @@ class ChecklistEntriesController < ApplicationController end # GET /checklist_entries/1 - def show - end + def show; end # GET /checklist_entries/new def new @@ -16,15 +17,14 @@ class ChecklistEntriesController < ApplicationController end # GET /checklist_entries/1/edit - def edit - end + def edit; end # POST /checklist_entries def create @checklist_entry = ChecklistEntry.new(checklist_entry_params) if @checklist_entry.save - redirect_to @checklist_entry.checklist, notice: 'Checklist entry was successfully created.' + redirect_to @checklist_entry.checklist, notice: "Checklist entry was successfully created." else render :new, status: :unprocessable_entity end @@ -33,7 +33,7 @@ class ChecklistEntriesController < ApplicationController # PATCH/PUT /checklist_entries/1 def update if @checklist_entry.update(checklist_entry_params) - redirect_to @checklist_entry.checklist, notice: 'Checklist entry was successfully updated.', + redirect_to @checklist_entry.checklist, notice: "Checklist entry was successfully updated.", status: :see_other else render :edit, status: :unprocessable_entity @@ -45,7 +45,7 @@ class ChecklistEntriesController < ApplicationController @checklist_entry.destroy! respond_to do |format| format.html do - redirect_to checklist_entries_url, notice: 'Checklist entry was successfully destroyed.', status: :see_other + redirect_to checklist_entries_url, notice: "Checklist entry was successfully destroyed.", status: :see_other end format.turbo_stream end diff --git a/app/controllers/checklists_controller.rb b/app/controllers/checklists_controller.rb index 02a20b8..89f1973 100644 --- a/app/controllers/checklists_controller.rb +++ b/app/controllers/checklists_controller.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class ChecklistsController < ApplicationController before_action :set_checklist, only: %i[show edit update destroy] @@ -7,8 +9,7 @@ class ChecklistsController < ApplicationController end # GET /checklists/1 - def show - end + def show; end # GET /checklists/new def new @@ -16,15 +17,14 @@ class ChecklistsController < ApplicationController end # GET /checklists/1/edit - def edit - end + def edit; end # POST /checklists def create @checklist = Checklist.new(checklist_params) if @checklist.save - redirect_to @checklist, notice: 'Checklist was successfully created.' + redirect_to @checklist, notice: "Checklist was successfully created." else render :new, status: :unprocessable_entity end @@ -33,7 +33,7 @@ class ChecklistsController < ApplicationController # PATCH/PUT /checklists/1 def update if @checklist.update(checklist_params) - redirect_to @checklist, notice: 'Checklist was successfully updated.', status: :see_other + redirect_to @checklist, notice: "Checklist was successfully updated.", status: :see_other else render :edit, status: :unprocessable_entity end @@ -42,7 +42,7 @@ class ChecklistsController < ApplicationController # DELETE /checklists/1 def destroy @checklist.destroy! - redirect_to checklists_url, notice: 'Checklist was successfully destroyed.', status: :see_other + redirect_to checklists_url, notice: "Checklist was successfully destroyed.", status: :see_other end private diff --git a/app/controllers/checks_controller.rb b/app/controllers/checks_controller.rb index 90c7a88..4b8669a 100644 --- a/app/controllers/checks_controller.rb +++ b/app/controllers/checks_controller.rb @@ -1,14 +1,19 @@ +# frozen_string_literal: true + class ChecksController < ApplicationController before_action :set_check, only: %i[show edit update destroy] # GET /checks or /checks.json def index - @pagy, @checks = pagy(Check.search(filter_params[:s])) + @pagy, @checks = if filter_params[:s] + pagy(Check.search(filter_params[:s]).order(:conformity_level)) + else + pagy(Check.all.order(:conformity_level)) + end end # GET /checks/1 or /checks/1.json - def show - end + def show; end # GET /checks/new def new @@ -16,8 +21,7 @@ class ChecksController < ApplicationController end # GET /checks/1/edit - def edit - end + def edit; end # POST /checks or /checks.json def create @@ -27,11 +31,11 @@ class ChecksController < ApplicationController if @check.save format.html do redirect_to check_url(@check), - notice: t('scaffold.model_created_successfully', model: @check.model_name.human) + notice: t("scaffold.model_created_successfully", model: @check.model_name.human) end format.json { render :show, status: :created, location: @check } else - flash[:alert] = t('there_were_errors', count: @check.errors.size) + flash[:alert] = t("there_were_errors", count: @check.errors.size) format.html { render :new, status: :unprocessable_entity } format.json { render json: @check.errors, status: :unprocessable_entity } end @@ -44,7 +48,7 @@ class ChecksController < ApplicationController if @check.update(check_params) format.html do redirect_to check_url(@check), - notice: t('scaffold.model_updated_successfully', model: @check.model_name.human) + notice: t("scaffold.model_updated_successfully", model: @check.model_name.human) end format.json { render :show, status: :ok, location: @check } else @@ -60,7 +64,7 @@ class ChecksController < ApplicationController respond_to do |format| format.html do - redirect_to checks_url, notice: t('scaffold.model_destroyed_successfully', model: @check.model_name.human) + redirect_to checks_url, notice: t("scaffold.model_destroyed_successfully", model: @check.model_name.human) end format.json { head :no_content } end @@ -79,6 +83,43 @@ class ChecksController < ApplicationController # Only allow a list of trusted parameters through. def check_params - params.require(:check).permit(:position, :name, :success_criterion, :success_criterion_html, :level) + params.require(:check).permit(:principle_id, + :number, + :name_de, + :name_en, + :standard_id, + :visual, + :auditory, + :physical, + :cognitive, + :applicable_to_app, + :applicable_to_web, + :external_number, + :conformity_level, + :conformity_notice_de, + :conformity_notice_en, + :priority, + :quick_criterion_de, + :quick_criterion_en, + :quick_fail_de, + :quick_fail_en, + :quick_fix_de, + :quick_fix_en, + :criterion_de, + :criterion_en, + :criterion_details_de, + :criterion_details_en, + :example_de, + :example_en, + :exemption_details_de, + :exemption_details_en, + :standard_text_de, + :standard_text_en, + :test_instructions, + :powerpoint_text_de, + :powerpoint_text_en, + :comment, + link_ids: [], + standard_ids: []) end end diff --git a/app/controllers/elements_controller.rb b/app/controllers/elements_controller.rb index 261e359..4824ec5 100644 --- a/app/controllers/elements_controller.rb +++ b/app/controllers/elements_controller.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class ElementsController < ApplicationController before_action :set_element, only: %i[show edit update destroy] @@ -7,8 +9,7 @@ class ElementsController < ApplicationController end # GET /elements/1 - def show - end + def show; end # GET /elements/new def new @@ -16,8 +17,7 @@ class ElementsController < ApplicationController end # GET /elements/1/edit - def edit - end + def edit; end # POST /elements def create @@ -28,11 +28,11 @@ class ElementsController < ApplicationController if @element.save checklist.checks.each do |check| - @element.success_criteria.create!(title: check.name, description_html: check.success_criterion_html, + @element.success_criteria.create!(title: check.t_name, description_html: check.t_criterion, level: check.level) end respond_to do |format| - format.html { redirect_to @element.report, notice: 'Element was successfully created.' } + format.html { redirect_to @element.report, notice: "Element was successfully created." } format.turbo_stream end else @@ -43,7 +43,7 @@ class ElementsController < ApplicationController # PATCH/PUT /elements/1 def update if @element.update(element_params) - redirect_to @element, notice: 'Element was successfully updated.', status: :see_other + redirect_to @element, notice: "Element was successfully updated.", status: :see_other else render :edit, status: :unprocessable_entity end @@ -52,7 +52,7 @@ class ElementsController < ApplicationController # DELETE /elements/1 def destroy @element.destroy! - redirect_to elements_url, notice: 'Element was successfully destroyed.', status: :see_other + redirect_to elements_url, notice: "Element was successfully destroyed.", status: :see_other end private diff --git a/app/controllers/home_controller.rb b/app/controllers/home_controller.rb index 13ff6f6..9ccfc38 100644 --- a/app/controllers/home_controller.rb +++ b/app/controllers/home_controller.rb @@ -1,5 +1,6 @@ # frozen_string_literal: true class HomeController < ApplicationController - def show; end + def show + end end diff --git a/app/controllers/link_categories_controller.rb b/app/controllers/link_categories_controller.rb index 7014f9c..cbccdf0 100644 --- a/app/controllers/link_categories_controller.rb +++ b/app/controllers/link_categories_controller.rb @@ -1,5 +1,7 @@ +# frozen_string_literal: true + class LinkCategoriesController < ApplicationController - before_action :set_link_category, only: %i[ show edit update destroy ] + before_action :set_link_category, only: %i[show edit update destroy] # GET /link_categories def index @@ -7,8 +9,7 @@ class LinkCategoriesController < ApplicationController end # GET /link_categories/1 - def show - end + def show; end # GET /link_categories/new def new @@ -16,8 +17,7 @@ class LinkCategoriesController < ApplicationController end # GET /link_categories/1/edit - def edit - end + def edit; end # POST /link_categories def create @@ -46,13 +46,14 @@ class LinkCategoriesController < ApplicationController end private - # Use callbacks to share common setup or constraints between actions. - def set_link_category - @link_category = LinkCategory.find(params[:id]) - end - # Only allow a list of trusted parameters through. - def link_category_params - params.require(:link_category).permit(:name, :description, :rich_text) - end + # Use callbacks to share common setup or constraints between actions. + def set_link_category + @link_category = LinkCategory.find(params[:id]) + end + + # Only allow a list of trusted parameters through. + def link_category_params + params.require(:link_category).permit(:name, :description, :rich_text) + end end diff --git a/app/controllers/links_controller.rb b/app/controllers/links_controller.rb index 810716f..20f1c7d 100644 --- a/app/controllers/links_controller.rb +++ b/app/controllers/links_controller.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class LinksController < ApplicationController before_action :set_link, only: %i[show edit update destroy] @@ -7,8 +9,7 @@ class LinksController < ApplicationController end # GET /links/1 - def show - end + def show; end # GET /links/new def new @@ -16,15 +17,14 @@ class LinksController < ApplicationController end # GET /links/1/edit - def edit - end + def edit; end # POST /links def create @link = Link.new(link_params) if @link.save - redirect_to @link, notice: 'Link was successfully created.' + redirect_to @link, notice: "Link was successfully created." else render :new, status: :unprocessable_entity end @@ -33,7 +33,7 @@ class LinksController < ApplicationController # PATCH/PUT /links/1 def update if @link.update(link_params) - redirect_to @link, notice: 'Link was successfully updated.', status: :see_other + redirect_to @link, notice: "Link was successfully updated.", status: :see_other else render :edit, status: :unprocessable_entity end @@ -42,7 +42,7 @@ class LinksController < ApplicationController # DELETE /links/1 def destroy @link.destroy! - redirect_to links_url, notice: 'Link was successfully destroyed.', status: :see_other + redirect_to links_url, notice: "Link was successfully destroyed.", status: :see_other end private diff --git a/app/controllers/reports_controller.rb b/app/controllers/reports_controller.rb index dfe6847..1ada068 100644 --- a/app/controllers/reports_controller.rb +++ b/app/controllers/reports_controller.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class ReportsController < ApplicationController before_action :set_report, only: %i[show edit update destroy work] @@ -12,26 +14,56 @@ class ReportsController < ApplicationController format.html format.pdf format.xlsx do - response.headers['Content-Disposition'] = %(attachment; filename="#{filename(@report, extension: 'xlsx')}") + response.headers["Content-Disposition"] = %(attachment; filename="#{filename(@report, extension: 'xlsx')}") render end format.xml do - response.headers['Content-Disposition'] = %(attachment; filename="#{filename(@report, extension: 'html')}") - render formats: [:odt], layout: false + response.headers["Content-Disposition"] = %(attachment; filename="#{filename(@report, extension: 'html')}") + render formats: [ :odt ], layout: false end format.rtf do - html = render_to_string(template: 'reports/show', formats: [:odt], + html = render_to_string(template: "reports/show", formats: [ :odt ], layout: false) rtf = "{\\rtf1\n#{PandocRuby.html(html).to_rtf}}" - send_data rtf, filename: filename(@report, extension: 'rtf') + send_data rtf, filename: filename(@report, extension: "rtf") end format.odt do html = render_to_string(layout: false) odt = PandocRuby.html(html).to_odt - send_data odt, filename: filename(@report, extension: 'odt') + send_data odt, filename: filename(@report, extension: "odt") end format.docx do - template = Sablon.template(Rails.root.join('lib/templates/docx/report.docx')) + send_file(Docx::Document.new.generate do |document| + document.heading1(@report.name) + document.paragraph(@report.comment_html) + # document.heading1("slfkj") + # document.paragraph("sldkfj") + @report.elements.each do |element| + document.heading2(element.title) + element.success_criteria.each do |sc| + document.heading3(sc.title) + document.paragraph(sc.description_html) + end + end + end, filename: filename(@report, extension: "docx"), + type: "application/vnd.openxmlformats-officedocument.wordprocessingml.document") + + return + + text = OpenXml::Docx::Elements::Text.new(@report.name) + run = OpenXml::Docx::Elements::Run.new + run.bold = true + run << text + paragraph = OpenXml::Docx::Elements::Paragraph.new + paragraph << run + + document = OpenXml::Docx::Package.new + document.document << paragraph + document.save(Rails.root.join("tmp", "output.docx")) + send_file Rails.root.join("tmp", "output.docx") + return + + template = Sablon.template(Rails.root.join("lib/templates/docx/report.docx")) context = { person: OpenStruct.new(first_name: @report.name), skills: [], @@ -40,10 +72,10 @@ class ReportsController < ApplicationController referees: [] } - template.render_to_file(Rails.root.join('tmp/output.docx'), context) - send_file Rails.root.join('tmp/output.docx'), - filename: filename(@report, extension: 'docx'), - type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' + template.render_to_file(Rails.root.join("tmp/output.docx"), context) + send_file Rails.root.join("tmp/output.docx"), + filename: filename(@report, extension: "docx"), + type: "application/vnd.openxmlformats-officedocument.wordprocessingml.document" end end end @@ -54,15 +86,14 @@ class ReportsController < ApplicationController end # GET /reports/1/edit - def edit - end + def edit; end # POST /reports def create @report = Report.new(report_params) if @report.save - redirect_to @report, notice: 'Report was successfully created.' + redirect_to @report, notice: "Report was successfully created." else render :new, status: :unprocessable_entity end @@ -71,7 +102,7 @@ class ReportsController < ApplicationController # PATCH/PUT /reports/1 def update if @report.update(report_params) - redirect_to @report, notice: 'Report was successfully updated.', status: :see_other + redirect_to @report, notice: "Report was successfully updated.", status: :see_other else render :edit, status: :unprocessable_entity end @@ -80,7 +111,7 @@ class ReportsController < ApplicationController # DELETE /reports/1 def destroy @report.destroy! - redirect_to reports_url, notice: 'Report was successfully destroyed.', status: :see_other + redirect_to reports_url, notice: "Report was successfully destroyed.", status: :see_other end def work @@ -99,7 +130,7 @@ class ReportsController < ApplicationController params.require(:report).permit(:name, :comment_html) end - def filename(report, extension: 'html') + def filename(report, extension: "html") "#{report.name}-#{Time.current.strftime('%Y%m%d%H%M')}.#{extension}" end end diff --git a/app/controllers/success_criteria_controller.rb b/app/controllers/success_criteria_controller.rb index a7fcf2a..7784d09 100644 --- a/app/controllers/success_criteria_controller.rb +++ b/app/controllers/success_criteria_controller.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class SuccessCriteriaController < ApplicationController before_action :set_success_criterion, only: %i[show edit update destroy] @@ -7,8 +9,7 @@ class SuccessCriteriaController < ApplicationController end # GET /success_criteria/1 - def show - end + def show; end # GET /success_criteria/new def new @@ -16,15 +17,14 @@ class SuccessCriteriaController < ApplicationController end # GET /success_criteria/1/edit - def edit - end + def edit; end # POST /success_criteria def create @success_criterion = SuccessCriterion.new(success_criterion_params) if @success_criterion.save - redirect_to @success_criterion, notice: 'Erfolgskriterium was successfully created.' + redirect_to @success_criterion, notice: "Erfolgskriterium was successfully created." else render :new, status: :unprocessable_entity end @@ -33,7 +33,7 @@ class SuccessCriteriaController < ApplicationController # PATCH/PUT /success_criteria/1 def update if @success_criterion.update(success_criterion_params) - redirect_to @success_criterion, notice: 'Erfolgskriterium was successfully updated.', status: :see_other + redirect_to @success_criterion, notice: "Erfolgskriterium was successfully updated.", status: :see_other else render :edit, status: :unprocessable_entity end @@ -44,7 +44,7 @@ class SuccessCriteriaController < ApplicationController @success_criterion.destroy! respond_to do |format| format.html do - redirect_to success_criteria_url, notice: 'Erfolgskriterium was successfully destroyed.', status: :see_other + redirect_to success_criteria_url, notice: "Erfolgskriterium was successfully destroyed.", status: :see_other end format.turbo_stream end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index ebb9bc8..70edee3 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -4,4 +4,16 @@ module ApplicationHelper include Pagy::Frontend delegate :filter_params, to: :controller + + def multilang_form_field(form, attribute, as: :text_field) + col_width = as == :rich_text_area ? 12 : 12 / I18n.available_locales.count + tag.div(class: "row") do + fields = I18n.available_locales.map { _1.to_s.split("-").first }.map do |lang| + tag.div(class: "col-lg-#{col_width}") do + form.send(as, "#{attribute}_#{lang}") + end + end + safe_join(fields) + end + end end diff --git a/app/helpers/checklist_entries_helper.rb b/app/helpers/checklist_entries_helper.rb index 09d2b52..e18ebce 100644 --- a/app/helpers/checklist_entries_helper.rb +++ b/app/helpers/checklist_entries_helper.rb @@ -1,2 +1,4 @@ +# frozen_string_literal: true + module ChecklistEntriesHelper end diff --git a/app/helpers/checklists_helper.rb b/app/helpers/checklists_helper.rb index 4652a79..b1da425 100644 --- a/app/helpers/checklists_helper.rb +++ b/app/helpers/checklists_helper.rb @@ -1,2 +1,4 @@ +# frozen_string_literal: true + module ChecklistsHelper end diff --git a/app/helpers/checks_helper.rb b/app/helpers/checks_helper.rb index ec8edd7..2515a9f 100644 --- a/app/helpers/checks_helper.rb +++ b/app/helpers/checks_helper.rb @@ -1,2 +1,4 @@ +# frozen_string_literal: true + module ChecksHelper end diff --git a/app/helpers/elements_helper.rb b/app/helpers/elements_helper.rb index fed28ea..d7f10ce 100644 --- a/app/helpers/elements_helper.rb +++ b/app/helpers/elements_helper.rb @@ -1,2 +1,4 @@ +# frozen_string_literal: true + module ElementsHelper end diff --git a/app/helpers/link_categories_helper.rb b/app/helpers/link_categories_helper.rb index c60b20f..d38d401 100644 --- a/app/helpers/link_categories_helper.rb +++ b/app/helpers/link_categories_helper.rb @@ -1,2 +1,4 @@ +# frozen_string_literal: true + module LinkCategoriesHelper end diff --git a/app/helpers/links_helper.rb b/app/helpers/links_helper.rb index f6bc988..038f107 100644 --- a/app/helpers/links_helper.rb +++ b/app/helpers/links_helper.rb @@ -1,2 +1,4 @@ +# frozen_string_literal: true + module LinksHelper end diff --git a/app/helpers/pdf_helper.rb b/app/helpers/pdf_helper.rb index 825b788..4f72ab3 100644 --- a/app/helpers/pdf_helper.rb +++ b/app/helpers/pdf_helper.rb @@ -1,17 +1,19 @@ +# frozen_string_literal: true + module PdfHelper def prepare_rich_text(rich_text) return rich_text - { del: 'strikethrough' }.each do |tag, replacement| + { del: "strikethrough" }.each do |tag, replacement| rich_text = rich_text.to_s.gsub("<#{tag}", "<#{replacement}") rich_text = rich_text.to_s.gsub("", "") end %w[div p del blockquote pre code].each do |tag| - rich_text = rich_text.to_s.gsub(%r{<#{tag}.*?>|}, '') + rich_text = rich_text.to_s.gsub(%r{<#{tag}.*?>|}, "") end - rich_text.gsub!(//, '') - rich_text.gsub!(%r{}, '

') + rich_text.gsub!(//, "") + rich_text.gsub!(%r{}, "

") rich_text end end diff --git a/app/helpers/reports_helper.rb b/app/helpers/reports_helper.rb index cae2f09..0eda9af 100644 --- a/app/helpers/reports_helper.rb +++ b/app/helpers/reports_helper.rb @@ -1,2 +1,4 @@ +# frozen_string_literal: true + module ReportsHelper end diff --git a/app/helpers/success_criteria_helper.rb b/app/helpers/success_criteria_helper.rb index 1fdada1..81cedeb 100644 --- a/app/helpers/success_criteria_helper.rb +++ b/app/helpers/success_criteria_helper.rb @@ -1,13 +1,15 @@ +# frozen_string_literal: true + module SuccessCriteriaHelper def success_criterion_result_icon_classes(sc) if sc.passed? - 'bi bi-check text-success' + "bi bi-check text-success" elsif sc.failed? - 'bi bi-exclamation-lg text-danger' + "bi bi-exclamation-lg text-danger" elsif sc.not_applicable? - 'bi bi-dash text-muted' + "bi bi-dash text-muted" else - 'bi bi-question text-warning' + "bi bi-question text-warning" end end @@ -16,13 +18,13 @@ module SuccessCriteriaHelper if edit_mode success_criterion else - [:edit, - success_criterion] + [ :edit, + success_criterion ] end - else + else success_criterion.element - end - link_to tag.i(class: 'bi bi-pencil'), + end + link_to tag.i(class: "bi bi-pencil"), path, class: "btn btn-#{edit_mode ? 'link text-warning' : 'link text-secondary'}" end diff --git a/app/javascript/application.js b/app/javascript/application.js index 5630ff0..4b59f32 100644 --- a/app/javascript/application.js +++ b/app/javascript/application.js @@ -5,3 +5,4 @@ import * as bootstrap from "bootstrap" import "trix" import "@rails/actiontext" + diff --git a/app/javascript/controllers/index.js b/app/javascript/controllers/index.js index 9c481e8..b5f1e6d 100644 --- a/app/javascript/controllers/index.js +++ b/app/javascript/controllers/index.js @@ -21,3 +21,4 @@ application.register("set-theme", SetThemeController) import ThemeSwitcherController from "./theme_switcher_controller" application.register("theme-switcher", ThemeSwitcherController) + diff --git a/app/lib/docx/document.rb b/app/lib/docx/document.rb new file mode 100644 index 0000000..a2d30cb --- /dev/null +++ b/app/lib/docx/document.rb @@ -0,0 +1,133 @@ +module Docx + class Document + include OpenXml::Docx::Elements + + def initialize + end + + def generate + yield(self) + + tmpfile = Tempfile.new("#{Time.current.to_f}.xlsx", Rails.root.join("tmp")) + _document.save(tmpfile.path) + tmpfile.path + end + + def heading1(text) + paragraph = create_paragraph(text) + paragraph.paragraph_style = "Heading 1" + _document.document << paragraph + end + + def heading2(text) + paragraph = create_paragraph(text) + paragraph.paragraph_style = "Heading 2" + _document.document << paragraph + end + + def heading3(text) + paragraph = create_paragraph(text) + paragraph.paragraph_style = "Heading 3" + _document.document << paragraph + end + + def paragraph(text) + html = Nokogiri::HTML5.fragment(text) + html.search(".trix-content").each do |node| + node.children.each do |child| + Rails.logger.debug { "content kids: #{child.class}: #{child.name} (#{child.children.size}): #{child.text}" } + case child + when Nokogiri::XML::Text + paragraph = create_paragraph(child.text) + _document.document << paragraph + when Nokogiri::XML::Element + case child.name + when "h1" + paragraph = create_paragraph(child.text) + paragraph.paragraph_style = "Heading 3" + when "div" + paragraph = Paragraph.new + paragraph.paragraph_style = "Body Text" + child.children.each do |node| + Rails.logger.debug { "div kids: #{node.class}: #{node.name} (#{node.children.size}): #{node.text}" } + case node.name + when "strong" + paragraph << create_run(node.text, bold: true) + when "em" + paragraph << create_run(node.text, italic: true) + when "del" + paragraph << create_run(node.text, strike_through: true) + when "br" + paragraph << create_run("\n") + else + paragraph << create_run(node.text) + end + end + when "ul" + # paragraph = Paragraph.new + # paragraph.paragraph_style = "Body Text" + # # Create an abstract numbering that describes a bulleted list: + # abstract_numbering = AbstractNumbering.new(0) + + # # Each numbering can have multiple levels. Define the first level as a bulleted list: + # level_0 = Level.new + # level_0.level = 0 + # level_0.start = 1 + # level_0.number_format = :bullet + # # This is the default bullet Word uses + # level_0.level_text = "\u00B7".encode("UTF-8") + # level_0.alignment = :left + # level_0.character_style.font.ascii = "Symbol" + # level_0.character_style.font.high_ansi = "Symbol" + # level_0.character_style.font.hint = :default + # level_0.paragraph_style.indentation.left = 720 + # level_0.paragraph_style.indentation.hanging = 360 + # abstract_numbering << level_0 + + # _document.numbering << abstract_numbering + when "ol" + else + paragraph = create_paragraph(child.text) + paragraph.paragraph_style = "Body Text" + end + + _document.document << paragraph + end + end + end + end + + private + + def create_run(content, bold: false, italic: false, strike_through: false) + text = Text.new(content) + text.space = :preserve + run = Run.new + run.bold = bold + run.italics = italic + run.strikethrough = strike_through + run << text + run + end + + def create_paragraph(content) + text = case content + when String + Text.new(content) + when ActionText::RichText + Text.new(content.to_plain_text) + else + Text.new(content.to_s) + end + run = Run.new + run << text + paragraph = Paragraph.new + paragraph << run + paragraph + end + + def _document + @_document ||= OpenXml::Docx::Package.new + end + end +end diff --git a/app/lib/link_checker.rb b/app/lib/link_checker.rb index bd44bef..7480316 100644 --- a/app/lib/link_checker.rb +++ b/app/lib/link_checker.rb @@ -1,7 +1,12 @@ +# frozen_string_literal: true + module LinkChecker UA = "Mozilla/5.0 (Android 4.4; Mobile; rv:41.0) Gecko/41.0 Firefox/41.0" - module_function def http(input) - response = Net::HTTP.get_response(URI.parse(input), {"User-Agent": UA}) + + module_function + + def http(input) + response = Net::HTTP.get_response(URI.parse(input), { 'User-Agent': UA }) # debugger case response when Net::HTTPSuccess @@ -13,4 +18,3 @@ module LinkChecker end end end - diff --git a/app/mailers/application_mailer.rb b/app/mailers/application_mailer.rb index d84cb6e..5cc63a0 100644 --- a/app/mailers/application_mailer.rb +++ b/app/mailers/application_mailer.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true class ApplicationMailer < ActionMailer::Base - default from: 'from@example.com' - layout 'mailer' + default from: "from@example.com" + layout "mailer" end diff --git a/app/models/action_text/rich_text.rb b/app/models/action_text/rich_text.rb index 5be8526..5c1a4a1 100644 --- a/app/models/action_text/rich_text.rb +++ b/app/models/action_text/rich_text.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module ActionText class RichText < Record before_save do diff --git a/app/models/admin/backup.rb b/app/models/admin/backup.rb index 40d6bbb..6483f8e 100644 --- a/app/models/admin/backup.rb +++ b/app/models/admin/backup.rb @@ -1,10 +1,12 @@ +# frozen_string_literal: true + module Admin class Backup class << self def zip create_records_xlsx - ZipFileGenerator.new(Rails.root.join('storage')).write + ZipFileGenerator.new(Rails.root.join("storage")).write end def db_xlsx @@ -21,7 +23,7 @@ module Admin end end end - path = Rails.root.join('storage/data.xls') + path = Rails.root.join("storage/data.xls") xlsx.serialize(path) path end @@ -29,7 +31,7 @@ module Admin private def file_path(name) - Rails.root.join('storage', name) + Rails.root.join("storage", name) end end end @@ -53,9 +55,9 @@ module Admin # Zip the input directory. def write entries = Dir.entries(@input_dir) - %w[. ..] - path = Rails.root.join('tmp', Time.now.to_i.to_s) + path = Rails.root.join("tmp", Time.now.to_i.to_s) ::Zip::File.open(path, create: true) do |zipfile| - write_entries entries, '', zipfile + write_entries entries, "", zipfile end path end @@ -65,7 +67,7 @@ module Admin # A helper method to make the recursion work. def write_entries(entries, path, zipfile) entries.each do |e| - zipfile_path = path == '' ? e : File.join(path, e) + zipfile_path = path == "" ? e : File.join(path, e) disk_file_path = File.join(@input_dir, zipfile_path) if File.directory? disk_file_path diff --git a/app/models/application_record.rb b/app/models/application_record.rb index 08dc537..20431b0 100644 --- a/app/models/application_record.rb +++ b/app/models/application_record.rb @@ -2,4 +2,17 @@ class ApplicationRecord < ActiveRecord::Base primary_abstract_class + + class << self + def translates_attributes(*attributes) + attributes.each do |attribute| + define_method("t_#{attribute}") do + lang = I18n.locale.to_s.split("-").first + send("#{attribute}_#{lang}") + end + end + end + + alias_method :translates_attribute, :translates_attributes + end end diff --git a/app/models/check.rb b/app/models/check.rb index c22a9b1..1caf36a 100644 --- a/app/models/check.rb +++ b/app/models/check.rb @@ -1,11 +1,67 @@ +# frozen_string_literal: true + class Check < ApplicationRecord include RichTextTargetBlank - enum :level, %i[A AA AAA] + belongs_to :principle - has_rich_text :success_criterion_html + has_and_belongs_to_many :links + has_and_belongs_to_many :standards - scope :search, lambda { |term| - joins("INNER JOIN action_text_rich_texts ON action_text_rich_texts.record_id = checks.id AND record_type = 'Check'").where('checks.name LIKE :term OR action_text_rich_texts.body_text LIKE :term', term: "%#{term}%") - } + accepts_nested_attributes_for :links, allow_destroy: true + + enum :conformity_level, %i[A AA AAA] + enum :priority, %i[highest high normal low] + + has_rich_text :conformity_notice_de + has_rich_text :conformity_notice_en + has_rich_text :quick_criterion_de + has_rich_text :quick_criterion_en + has_rich_text :quick_fail_de + has_rich_text :quick_fail_en + has_rich_text :quick_fix_de + has_rich_text :quick_fix_en + + has_rich_text :criterion_de + has_rich_text :criterion_en + has_rich_text :criterion_details_de + has_rich_text :criterion_details_en + has_rich_text :example_de + has_rich_text :example_en + has_rich_text :exemption_details_de + has_rich_text :exemption_details_en + has_rich_text :standard_text_de + has_rich_text :standard_text_en + + has_rich_text :test_instructions + + has_rich_text :powerpoint_text_de + has_rich_text :powerpoint_text_en + + has_rich_text :comment + + translates_attributes :name, + :conformity_notice, + :quick_criterion, + :quick_fail, + :quick_fix, + :criterion, + :criterion_details, + :example, + :exemption_details, + :standard_text, + :powerpoint_text + + scope(:search, lambda do |term| + # TODO: Search only fields for current locale. + joins("INNER JOIN action_text_rich_texts ON action_text_rich_texts.record_id = checks.id AND record_type = 'Check'").where("checks.name_de LIKE :term OR checks.name_de LIKE :term OR action_text_rich_texts.body LIKE :term", term: "%#{term}%").distinct + end) + + def display_target_disabilities + %i[visual auditory physical cognitive].select { |d| send(:"#{d}?") }.map { |d| I18n.t("disability.#{d}") }.map(&:first).join(", ") + end + + def display_applicabilities + %i[applicable_to_app applicable_to_web].select { |a| send(:"#{a}?") }.map { |a| I18n.t("applicability.#{a}") }.map(&:first).join(", ") + end end diff --git a/app/models/checklist.rb b/app/models/checklist.rb index 084ded2..4a34c94 100644 --- a/app/models/checklist.rb +++ b/app/models/checklist.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class Checklist < ApplicationRecord has_many :checklist_entries, -> { order(position: :asc) }, dependent: :destroy, inverse_of: :checklist has_many :checks, through: :checklist_entries diff --git a/app/models/checklist_entry.rb b/app/models/checklist_entry.rb index 0bde766..ef537e4 100644 --- a/app/models/checklist_entry.rb +++ b/app/models/checklist_entry.rb @@ -1,12 +1,15 @@ +# frozen_string_literal: true + class ChecklistEntry < ApplicationRecord belongs_to :checklist belongs_to :check before_validation :set_position - after_validation :normalize_positions + before_create :update_positions + before_update :update_positions, if: :position_changed? def set_position - self.position ||= checklist.checklist_entries.maximum(:position).to_i + 1 + self.position ||= (checklist.checklist_entries.pluck(:position).max || 0) + 1 end def normalize_positions @@ -15,4 +18,11 @@ class ChecklistEntry < ApplicationRecord # entry.update_column(:position, index + 1) if entry.position != index + 1 # end end + + def update_positions + if position_was + checklist.checklist_entries.where("position > ?", position_was).update_all("position = position - 1") + end + checklist.checklist_entries.where(position: position..).update_all("position = position + 1") + end end diff --git a/app/models/concerns/rich_text_target_blank.rb b/app/models/concerns/rich_text_target_blank.rb index 0405983..82b3c2e 100644 --- a/app/models/concerns/rich_text_target_blank.rb +++ b/app/models/concerns/rich_text_target_blank.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module RichTextTargetBlank extend ActiveSupport::Concern @@ -11,7 +13,7 @@ module RichTextTargetBlank rich_text_attribute = send(name) if rich_text_attribute.present? doc = Nokogiri::HTML::DocumentFragment.parse(rich_text_attribute.body.to_html) - doc.css('a').each { |a| a['target'] ||= '_blank' } + doc.css("a").each { |a| a["target"] ||= "_blank" } rich_text_attribute.body = doc.to_html end end diff --git a/app/models/element.rb b/app/models/element.rb index 54ed6ff..333ef9f 100644 --- a/app/models/element.rb +++ b/app/models/element.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class Element < ApplicationRecord attr_accessor :checklist_id @@ -22,8 +24,8 @@ class Element < ApplicationRecord return nil if possible_levels.empty? - puts possible_levels.inspect - puts min_failed + Rails.logger.debug possible_levels.inspect + Rails.logger.debug min_failed possible_levels[possible_levels.find_index(min_failed) - 1] end diff --git a/app/models/link.rb b/app/models/link.rb index 88e8563..067e159 100644 --- a/app/models/link.rb +++ b/app/models/link.rb @@ -1,7 +1,11 @@ -require 'net/http' +# frozen_string_literal: true + +require "net/http" class Link < ApplicationRecord belongs_to :link_category + has_and_belongs_to_many :checks + has_rich_text :description_html validates :url, :text, presence: true @@ -10,13 +14,21 @@ class Link < ApplicationRecord before_validation :ensure_absolute_url + def t_text + text + end + def ok? - fail_count == 0 + fail_count.zero? + end + + def to_s + "#{text} (#{url})" end private - USER_AGENT = 'Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0' + USER_AGENT = "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0" def check_url(input = url, add_error = true) response = begin diff --git a/app/models/link_category.rb b/app/models/link_category.rb index 76de740..069e2a9 100644 --- a/app/models/link_category.rb +++ b/app/models/link_category.rb @@ -1,5 +1,11 @@ +# frozen_string_literal: true + class LinkCategory < ApplicationRecord has_many :links - - has_rich_text :description_html + + has_rich_text :description + + def t_name + name + end end diff --git a/app/models/pdf_documents/base.rb b/app/models/pdf_documents/base.rb index 6c7ecef..c21d790 100644 --- a/app/models/pdf_documents/base.rb +++ b/app/models/pdf_documents/base.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module PdfDocuments class Base attr_reader :params @@ -11,7 +13,7 @@ module PdfDocuments # exta_bold: 'vendor/assets/fonts/Lexend-ExtraBold.ttf', # italic: 'vendor/assets/fonts/Lexend-Regular.ttf' # }) - @prawn_document.font 'Helvetica', size: 12 + @prawn_document.font "Helvetica", size: 12 @params = OpenStruct.new(params) end @@ -47,7 +49,7 @@ module PdfDocuments end def hr - @prawn_document.markup '
' + @prawn_document.markup "
" end def markup_options @@ -63,12 +65,12 @@ module PdfDocuments end def logo - @prawn_document.image 'app/assets/images/logo-apfelschule.png', width: 150 + @prawn_document.image "app/assets/images/logo-apfelschule.png", width: 150 @prawn_document.move_down 30 end def prepare_rich_text(rich_text) - { h1: 'h4' }.each do |tag, replacement| + { h1: "h4" }.each do |tag, replacement| rich_text = rich_text.to_s.gsub("<#{tag}", "<#{replacement}") rich_text = rich_text.to_s.gsub("", "") end diff --git a/app/models/pdf_documents/customer_report.rb b/app/models/pdf_documents/customer_report.rb index 048ca10..e6e98d8 100644 --- a/app/models/pdf_documents/customer_report.rb +++ b/app/models/pdf_documents/customer_report.rb @@ -1,19 +1,21 @@ +# frozen_string_literal: true + module PdfDocuments class CustomerReport < Base private def generate logo - @prawn_document.formatted_text_box [{ + @prawn_document.formatted_text_box [ { text: "Dieses Dokument wurd am #{Time.current.strftime('%d %B %Y')} um #{Time.current.strftime('%H:%M:%S')} erstellt.", size: 8, align: :right - }], align: :right + } ], align: :right heading1 params.report.name rich_text params.report.comment_html params.report.elements.each.with_index(1) do |element, element_index| heading2 "#{element_index} #{element.title}" - formatted_text [{ text: element.path, styles: %i[bold italic underline] }] + formatted_text [ { text: element.path, styles: %i[bold italic underline] } ] move_down(5) rich_text element.description_html diff --git a/app/models/principle.rb b/app/models/principle.rb new file mode 100644 index 0000000..d30baf4 --- /dev/null +++ b/app/models/principle.rb @@ -0,0 +1,3 @@ +class Principle < ApplicationRecord + translates_attribute :name +end diff --git a/app/models/report.rb b/app/models/report.rb index b1a87fb..2b6974f 100644 --- a/app/models/report.rb +++ b/app/models/report.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class Report < ApplicationRecord has_rich_text :comment_html diff --git a/app/models/standard.rb b/app/models/standard.rb new file mode 100644 index 0000000..a84c93f --- /dev/null +++ b/app/models/standard.rb @@ -0,0 +1,5 @@ +class Standard < ApplicationRecord + has_and_belongs_to_many :checks + + translates_attribute :name +end diff --git a/app/models/success_criterion.rb b/app/models/success_criterion.rb index b77d991..11d5837 100644 --- a/app/models/success_criterion.rb +++ b/app/models/success_criterion.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class SuccessCriterion < ApplicationRecord enum :result, %i[passed failed not_applicable] enum :level, %i[A AA AAA] diff --git a/app/views/checklist_entries/_checklist_entry.json.jbuilder b/app/views/checklist_entries/_checklist_entry.json.jbuilder index ef3eaed..6a3befb 100644 --- a/app/views/checklist_entries/_checklist_entry.json.jbuilder +++ b/app/views/checklist_entries/_checklist_entry.json.jbuilder @@ -1,2 +1,4 @@ +# frozen_string_literal: true + json.extract! checklist_entry, :id, :checklist_id, :check_id, :position, :created_at, :updated_at json.url checklist_entry_url(checklist_entry, format: :json) diff --git a/app/views/checklist_entries/index.json.jbuilder b/app/views/checklist_entries/index.json.jbuilder index be6f6df..55dbe8e 100644 --- a/app/views/checklist_entries/index.json.jbuilder +++ b/app/views/checklist_entries/index.json.jbuilder @@ -1 +1,3 @@ +# frozen_string_literal: true + json.array! @checklist_entries, partial: "checklist_entries/checklist_entry", as: :checklist_entry diff --git a/app/views/checklist_entries/show.json.jbuilder b/app/views/checklist_entries/show.json.jbuilder index f479642..e93da40 100644 --- a/app/views/checklist_entries/show.json.jbuilder +++ b/app/views/checklist_entries/show.json.jbuilder @@ -1 +1,3 @@ +# frozen_string_literal: true + json.partial! "checklist_entries/checklist_entry", checklist_entry: @checklist_entry diff --git a/app/views/checklists/_checklist.json.jbuilder b/app/views/checklists/_checklist.json.jbuilder index d3ffcaa..ae96ec5 100644 --- a/app/views/checklists/_checklist.json.jbuilder +++ b/app/views/checklists/_checklist.json.jbuilder @@ -1,2 +1,4 @@ +# frozen_string_literal: true + json.extract! checklist, :id, :code, :name, :description_html, :created_at, :updated_at json.url checklist_url(checklist, format: :json) diff --git a/app/views/checklists/index.json.jbuilder b/app/views/checklists/index.json.jbuilder index 28199e0..e25f6db 100644 --- a/app/views/checklists/index.json.jbuilder +++ b/app/views/checklists/index.json.jbuilder @@ -1 +1,3 @@ +# frozen_string_literal: true + json.array! @checklists, partial: "checklists/checklist", as: :checklist diff --git a/app/views/checklists/show.json.jbuilder b/app/views/checklists/show.json.jbuilder index 1c1d9ba..27c5a6c 100644 --- a/app/views/checklists/show.json.jbuilder +++ b/app/views/checklists/show.json.jbuilder @@ -1 +1,3 @@ +# frozen_string_literal: true + json.partial! "checklists/checklist", checklist: @checklist diff --git a/app/views/checks/_check.html.erb b/app/views/checks/_check.html.erb deleted file mode 100644 index 0df1c67..0000000 --- a/app/views/checks/_check.html.erb +++ /dev/null @@ -1,22 +0,0 @@ -
-

- <%= Check.human_attribute_name(:position) %>: - <%= check.position %> -

- -

- <%= Check.human_attribute_name(:name) %>: - <%= check.name %> -

- -

- <%= Check.human_attribute_name(:success_criterion_html) %>: - <%= check.success_criterion_html %> -

- -

- <%= Check.human_attribute_name(:level) %>: - <%= check.level %> -

- -
diff --git a/app/views/checks/_check.html.slim b/app/views/checks/_check.html.slim new file mode 100644 index 0000000..79f9a08 --- /dev/null +++ b/app/views/checks/_check.html.slim @@ -0,0 +1,68 @@ +div id=dom_id(check) + table.table + tbody + tr + th = Check.human_attribute_name(:id) + td = check.id + tr + th = Principle.model_name.human + td = check.principle&.t_name + tr + th = Check.human_attribute_name(:number) + td = check.number + tr + th = Check.human_attribute_name(:name) + td = check.t_name + tr + th = Standard.model_name.human(count: check.standard_ids.size) + td = check.standards.map(&:t_name).join(", ") + tr + th = Check.human_attribute_name(:target_disabilities) + td = check.display_target_disabilities + tr + th = Check.human_attribute_name(:applicabilities) + td = check.display_applicabilities + tr + th = Check.human_attribute_name(:external_number) + td = check.external_number + tr + th = Check.human_attribute_name(:conformity_level) + td = check.conformity_level + tr + th = Check.human_attribute_name(:conformity_notice_de) + td = check.conformity_notice_de + tr + th = Check.human_attribute_name(:conformity_notice_en) + td = check.conformity_notice_en + tr + th = Check.human_attribute_name(:priority) + td = check.priority + tr + th = Check.human_attribute_name(:quick_criterion_de) + td = check.quick_criterion_de + tr + th = Check.human_attribute_name(:quick_criterion_en) + td = check.quick_criterion_en + tr + th = Check.human_attribute_name(:quick_fail_de) + td = check.quick_fail_de + tr + th = Check.human_attribute_name(:quick_fail_en) + td = check.quick_fail_en + tr + th = Check.human_attribute_name(:quick_fix_de) + td = check.quick_fix_de + tr + th = Check.human_attribute_name(:quick_fix_en) + td = check.quick_fix_en + tr + th = Link.model_name.human(count: check.links.size) + td + .row + .col + - check.links.map(&:link_category).uniq.each do |category| + span = category.name + ul + - check.links.select{ _1.link_category == category }.map { |link| link_to link.text, link.url, target: :_blank }.each do |link| + li = link + \ No newline at end of file diff --git a/app/views/checks/_check.json.jbuilder b/app/views/checks/_check.json.jbuilder index 128c258..743333d 100644 --- a/app/views/checks/_check.json.jbuilder +++ b/app/views/checks/_check.json.jbuilder @@ -1,2 +1,4 @@ +# frozen_string_literal: true + json.extract! check, :id, :position, :name, :success_criterion_html, :level, :created_at, :updated_at json.url check_url(check, format: :json) diff --git a/app/views/checks/_form.html.erb b/app/views/checks/_form.html.erb deleted file mode 100644 index ab0d482..0000000 --- a/app/views/checks/_form.html.erb +++ /dev/null @@ -1,7 +0,0 @@ -<%= bootstrap_form_with(model: check, remote: true) do |form| %> - <%= form.text_field :position %> - <%= form.text_field :name %> - <%= form.rich_text_area :success_criterion_html %> - <%= form.select :level, Check.levels.keys, add_blank: !form.object.level.present? %> - <%= form.submit %> -<% end %> diff --git a/app/views/checks/_form.html.slim b/app/views/checks/_form.html.slim new file mode 100644 index 0000000..72933a1 --- /dev/null +++ b/app/views/checks/_form.html.slim @@ -0,0 +1,53 @@ += bootstrap_form_with(model: check, remote: true) do |form| + h2 Details + = form.collection_select :principle_id, Principle.all.sort_by(&:t_name), :id, :t_name + = form.text_field :number + = multilang_form_field(form, :name) + = form.collection_check_boxes :standard_ids, Standard.all.sort_by(&:t_name), :id, :t_name, include_blank: true + h2 Zugänglichkeit + .row + .col-md-3 + = form.check_box :visual, label: t("disability.visual").capitalize + .col-md-3 + = form.check_box :auditory, label: t("disability.auditory").capitalize + .col-md-3 + = form.check_box :physical, label: t("disability.physical").capitalize + .col-md-3 + = form.check_box :cognitive, label: t("disability.cognitive").capitalize + h2 Anwendbarkeit + .row + .col-md-6 + = form.check_box :applicable_to_web, label: t("applicability.applicable_to_web").capitalize + .col-md-6 + = form.check_box :applicable_to_app, label: t("applicability.applicable_to_app").capitalize + h2 Richtlinie + = form.text_field :external_number + = form.select :conformity_level, Check.conformity_levels.keys, include_blank: true + = multilang_form_field(form, :conformity_notice, as: :rich_text_area) + + = form.select :priority, Check.priorities.keys.map{ [t("priority.#{_1}"), _1] }, include_blank: true + h2 Quick Infos + = multilang_form_field(form, :quick_criterion, as: :rich_text_area) + = multilang_form_field(form, :quick_fail, as: :rich_text_area) + = multilang_form_field(form, :quick_fix, as: :rich_text_area) + + h2 Regular-Kriterium + = multilang_form_field(form, :criterion, as: :rich_text_area) + = multilang_form_field(form, :criterion_details, as: :rich_text_area) + = multilang_form_field(form, :example, as: :rich_text_area) + = multilang_form_field(form, :exemption_details, as: :rich_text_area) + = multilang_form_field(form, :standard_text, as: :rich_text_area) + + h2 Intern + = form.rich_text_area :test_instructions + = multilang_form_field(form, :powerpoint_text, as: :rich_text_area) + = form.rich_text_area :comment + + h2 Links + - LinkCategory.all.sort_by(&:t_name).each do |c| + h3 = c.t_name + = form.collection_check_boxes(:link_ids, c.links.sort_by(&:t_text), :id, :to_s, hide_label: true) + / = form.collection_check_boxes :link_ids, Link.all.sort_by(&:text), :id, :to_s + + / = form.rich_text_area :success_criterion_de + = form.submit diff --git a/app/views/checks/index.html.erb b/app/views/checks/index.html.erb.disabled similarity index 61% rename from app/views/checks/index.html.erb rename to app/views/checks/index.html.erb.disabled index dee0791..026e6d0 100644 --- a/app/views/checks/index.html.erb +++ b/app/views/checks/index.html.erb.disabled @@ -15,18 +15,24 @@ - - + - + + + + + <% @checks.each do |check| %> - - - - + + + + + + + <% end %> diff --git a/app/views/checks/index.html.slim b/app/views/checks/index.html.slim new file mode 100644 index 0000000..830ab44 --- /dev/null +++ b/app/views/checks/index.html.slim @@ -0,0 +1,51 @@ +h1 + = t("scaffold.pagetitle_index", model: Check.model_name.human(count: 2)) += bootstrap_form_with(url: checks_path(page: params[:page]), method: :get, scope: :filter) do |form| + = form.hidden_field :page, value: params[:page] if params[:page] + .row + .col-md-3 + = form.text_field(:s, placeholder: "suchen...", hide_label: true, value: filter_params[:s]) + .col + = form.submit name: "", value: "Suchen" + = link_to "Filter löschen", checks_path, class: "btn btn-outline-secondary ms-3" if filter_params[:s] +table.table.table-striped + thead + tr + th ID + th + = Check.human_attribute_name(:number) + th + = Check.human_attribute_name(:name) + th + = Check.human_attribute_name(:standard_ids) + th + = Check.human_attribute_name(:target_disability) + th + = Check.human_attribute_name(:applicability) + th + = Check.human_attribute_name(:external_number) + th + = Check.human_attribute_name(:conformity_level) + tbody + - @checks.each do |check| + tr + td = link_to check.id, check + td + = link_to(check.number, check) + td + = link_to check.t_name&.truncate(64), check + td + = link_to check.standards.map(&:t_name).join(", "), check + td + = link_to check.display_target_disabilities, check + td + = link_to check.display_applicabilities, check + td + = link_to check.external_number, check + td + = link_to check.conformity_level, check +.my-3 + == pagy_info(@pagy) +== pagy_bootstrap_nav(@pagy) +.action-row + = link_to t("scaffold.link_new", model: Check.model_name.human), new_check_path diff --git a/app/views/checks/index.json.jbuilder b/app/views/checks/index.json.jbuilder index fb8a917..10a5125 100644 --- a/app/views/checks/index.json.jbuilder +++ b/app/views/checks/index.json.jbuilder @@ -1 +1,3 @@ +# frozen_string_literal: true + json.array! @checks, partial: "checks/check", as: :check diff --git a/app/views/checks/show.html.erb b/app/views/checks/show.html.erb index e15c1b1..61ed134 100644 --- a/app/views/checks/show.html.erb +++ b/app/views/checks/show.html.erb @@ -1,4 +1,4 @@ -

<%= t("scaffold.pagetitle_show", model: @check.class.model_name.human) %>

+

<%= @check.t_name %>

<%= render @check %> diff --git a/app/views/checks/show.json.jbuilder b/app/views/checks/show.json.jbuilder index bd47a45..8f4aa98 100644 --- a/app/views/checks/show.json.jbuilder +++ b/app/views/checks/show.json.jbuilder @@ -1 +1,3 @@ +# frozen_string_literal: true + json.partial! "checks/check", check: @check diff --git a/app/views/elements/_element.json.jbuilder b/app/views/elements/_element.json.jbuilder index 1656599..9cd2700 100644 --- a/app/views/elements/_element.json.jbuilder +++ b/app/views/elements/_element.json.jbuilder @@ -1,2 +1,4 @@ +# frozen_string_literal: true + json.extract! element, :id, :report_id, :path, :title, :description_html, :created_at, :updated_at json.url element_url(element, format: :json) diff --git a/app/views/elements/index.json.jbuilder b/app/views/elements/index.json.jbuilder index d9f38ab..824db2e 100644 --- a/app/views/elements/index.json.jbuilder +++ b/app/views/elements/index.json.jbuilder @@ -1 +1,3 @@ +# frozen_string_literal: true + json.array! @elements, partial: "elements/element", as: :element diff --git a/app/views/elements/show.json.jbuilder b/app/views/elements/show.json.jbuilder index d6d6270..622bc77 100644 --- a/app/views/elements/show.json.jbuilder +++ b/app/views/elements/show.json.jbuilder @@ -1 +1,3 @@ +# frozen_string_literal: true + json.partial! "elements/element", element: @element diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 440e2ef..c7f4d69 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -1,5 +1,5 @@ - data-controller="set-theme"> +" data-controller="set-theme"> a11ydive diff --git a/app/views/link_categories/_link_category.html.erb b/app/views/link_categories/_link_category.html.erb index dba9748..ce70e36 100644 --- a/app/views/link_categories/_link_category.html.erb +++ b/app/views/link_categories/_link_category.html.erb @@ -6,7 +6,7 @@

Description: - <%= link_category.description_html %> + <%= link_category.description %>

diff --git a/app/views/link_categories/_link_category.json.jbuilder b/app/views/link_categories/_link_category.json.jbuilder index fe0be43..6a3da26 100644 --- a/app/views/link_categories/_link_category.json.jbuilder +++ b/app/views/link_categories/_link_category.json.jbuilder @@ -1,2 +1,4 @@ +# frozen_string_literal: true + json.extract! link_category, :id, :name, :description, :rich_text, :created_at, :updated_at json.url link_category_url(link_category, format: :json) diff --git a/app/views/link_categories/index.html.erb b/app/views/link_categories/index.html.erb index 34ac9e4..8005b2a 100644 --- a/app/views/link_categories/index.html.erb +++ b/app/views/link_categories/index.html.erb @@ -18,7 +18,7 @@ - + <% end %> diff --git a/app/views/link_categories/index.json.jbuilder b/app/views/link_categories/index.json.jbuilder index b68de09..5c313a1 100644 --- a/app/views/link_categories/index.json.jbuilder +++ b/app/views/link_categories/index.json.jbuilder @@ -1 +1,3 @@ +# frozen_string_literal: true + json.array! @link_categories, partial: "link_categories/link_category", as: :link_category diff --git a/app/views/link_categories/show.json.jbuilder b/app/views/link_categories/show.json.jbuilder index ec040cb..0076302 100644 --- a/app/views/link_categories/show.json.jbuilder +++ b/app/views/link_categories/show.json.jbuilder @@ -1 +1,3 @@ +# frozen_string_literal: true + json.partial! "link_categories/link_category", link_category: @link_category diff --git a/app/views/links/_link.json.jbuilder b/app/views/links/_link.json.jbuilder index 8857558..cc270f2 100644 --- a/app/views/links/_link.json.jbuilder +++ b/app/views/links/_link.json.jbuilder @@ -1,3 +1,6 @@ -json.extract! link, :id, :url, :text, :description, :last_check_at, :fail_count, :link_category_id, :created_at, :updated_at +# frozen_string_literal: true + +json.extract! link, :id, :url, :text, :description, :last_check_at, :fail_count, :link_category_id, :created_at, + :updated_at json.url link_url(link, format: :json) json.description link.description.to_s diff --git a/app/views/links/index.json.jbuilder b/app/views/links/index.json.jbuilder index 7b13bad..1367af9 100644 --- a/app/views/links/index.json.jbuilder +++ b/app/views/links/index.json.jbuilder @@ -1 +1,3 @@ +# frozen_string_literal: true + json.array! @links, partial: "links/link", as: :link diff --git a/app/views/links/show.json.jbuilder b/app/views/links/show.json.jbuilder index 79e4f78..6a9c888 100644 --- a/app/views/links/show.json.jbuilder +++ b/app/views/links/show.json.jbuilder @@ -1 +1,3 @@ +# frozen_string_literal: true + json.partial! "links/link", link: @link diff --git a/app/views/reports/_report.json.jbuilder b/app/views/reports/_report.json.jbuilder index 5012ee9..3c8f009 100644 --- a/app/views/reports/_report.json.jbuilder +++ b/app/views/reports/_report.json.jbuilder @@ -1,2 +1,4 @@ +# frozen_string_literal: true + json.extract! report, :id, :name, :comment_html, :created_at, :updated_at json.url report_url(report, format: :json) diff --git a/app/views/reports/index.json.jbuilder b/app/views/reports/index.json.jbuilder index 31811f6..5da3e58 100644 --- a/app/views/reports/index.json.jbuilder +++ b/app/views/reports/index.json.jbuilder @@ -1 +1,3 @@ +# frozen_string_literal: true + json.array! @reports, partial: "reports/report", as: :report diff --git a/app/views/reports/show.json.jbuilder b/app/views/reports/show.json.jbuilder index b5a5508..5ff9f54 100644 --- a/app/views/reports/show.json.jbuilder +++ b/app/views/reports/show.json.jbuilder @@ -1 +1,3 @@ +# frozen_string_literal: true + json.partial! "reports/report", report: @report diff --git a/app/views/reports/show.xlsx.axlsx b/app/views/reports/show.xlsx.axlsx index 92d2d08..1087d58 100644 --- a/app/views/reports/show.xlsx.axlsx +++ b/app/views/reports/show.xlsx.axlsx @@ -1,3 +1,5 @@ +# frozen_string_literal: true + wb = xlsx_package.workbook wb.add_worksheet(name: "Erfolgskriterien") do |sheet| sheet.add_row SuccessCriterion.column_names @@ -7,4 +9,4 @@ wb.add_worksheet(name: "Erfolgskriterien") do |sheet| sheet.add_row sc.attributes.values end end -end \ No newline at end of file +end diff --git a/app/views/success_criteria/_success_criterion.json.jbuilder b/app/views/success_criteria/_success_criterion.json.jbuilder index 81d1a20..672caae 100644 --- a/app/views/success_criteria/_success_criterion.json.jbuilder +++ b/app/views/success_criteria/_success_criterion.json.jbuilder @@ -1,3 +1,5 @@ +# frozen_string_literal: true + json.extract! success_criterion, :id, :element_id, :title, :description_html, :level, :result, :comment_html, :created_at, :updated_at json.url success_criterion_url(success_criterion, format: :json) diff --git a/app/views/success_criteria/index.json.jbuilder b/app/views/success_criteria/index.json.jbuilder index 8ee481b..96dcdc7 100644 --- a/app/views/success_criteria/index.json.jbuilder +++ b/app/views/success_criteria/index.json.jbuilder @@ -1 +1,3 @@ +# frozen_string_literal: true + json.array! @success_criteria, partial: "success_criteria/success_criterion", as: :success_criterion diff --git a/app/views/success_criteria/show.json.jbuilder b/app/views/success_criteria/show.json.jbuilder index 5df804d..463c139 100644 --- a/app/views/success_criteria/show.json.jbuilder +++ b/app/views/success_criteria/show.json.jbuilder @@ -1 +1,3 @@ +# frozen_string_literal: true + json.partial! "success_criteria/success_criterion", success_criterion: @success_criterion diff --git a/bin/brakeman b/bin/brakeman new file mode 100755 index 0000000..ae3a448 --- /dev/null +++ b/bin/brakeman @@ -0,0 +1,9 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +require 'rubygems' +require 'bundler/setup' + +ARGV.unshift('--ensure-latest') + +load Gem.bin_path('brakeman', 'brakeman') diff --git a/bin/entrypoint b/bin/entrypoint index 2f2c947..54e4d9b 100755 --- a/bin/entrypoint +++ b/bin/entrypoint @@ -1,20 +1,23 @@ -#!/bin/bash +#!/bin/ash + set -e -echo "1: ${1}" -echo "2: ${2}" if [ -f tmp/pids/server.pid ]; then rm tmp/pids/server.pid fi # Make the if statement match any invocation of the "rails server" command if [[ "${1}" == *rails ]] && ([ "${2}" == "server" ] || [ "${2}" == "s" ]); then + echo "+ preparing database..." + ./bin/rails db:prepare + echo "- preparing database done." - if [ ! -f /app/no_migrate ] && [ ! -v NO_MIGRATE ]; then - echo "+ preparing database..." - ./bin/rails db:prepare - echo "- preparing database done." + if [ -n "$ASSETS_PATH" ]; then + echo "+ copying assets..." + cp -nr public/* $ASSETS_PATH + echo "- copying assets done." fi + fi # Execute the given or default command: diff --git a/bin/rubocop b/bin/rubocop new file mode 100755 index 0000000..f45b065 --- /dev/null +++ b/bin/rubocop @@ -0,0 +1,10 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +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/bin/setup b/bin/setup index d38bf9f..c823853 100755 --- a/bin/setup +++ b/bin/setup @@ -1,8 +1,8 @@ #!/usr/bin/env ruby require "fileutils" -# path to your application root. APP_ROOT = File.expand_path("..", __dir__) +APP_NAME = "a11yist" def system!(*args) system(*args, exception: true) @@ -17,9 +17,6 @@ FileUtils.chdir APP_ROOT do system! "gem install bundler --conservative" system("bundle check") || system!("bundle install") - # Install JavaScript dependencies - system("yarn check --check-files") || system!("yarn install") - # puts "\n== Copying sample files ==" # unless File.exist?("config/database.yml") # FileUtils.cp "config/database.yml.sample", "config/database.yml" @@ -33,4 +30,8 @@ FileUtils.chdir APP_ROOT do puts "\n== Restarting application server ==" system! "bin/rails restart" + + # puts "\n== Configuring puma-dev ==" + # system "ln -nfs #{APP_ROOT} ~/.puma-dev/#{APP_NAME}" + # system "curl -Is https://#{APP_NAME}.test/up | head -n 1" end diff --git a/config/boot.rb b/config/boot.rb index b9e460c..988a5dd 100644 --- a/config/boot.rb +++ b/config/boot.rb @@ -1,4 +1,4 @@ -ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) -require 'bundler/setup' # Set up gems listed in the Gemfile. -require 'bootsnap/setup' # Speed up boot time by caching expensive operations. +require "bundler/setup" # Set up gems listed in the Gemfile. +require "bootsnap/setup" # Speed up boot time by caching expensive operations. diff --git a/config/database.yml b/config/database.yml index 796466b..56d378d 100644 --- a/config/database.yml +++ b/config/database.yml @@ -8,6 +8,7 @@ default: &default adapter: sqlite3 pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> timeout: 5000 + default_transaction_mode: IMMEDIATE development: <<: *default diff --git a/config/environments/development.rb b/config/environments/development.rb index a72b7d7..c6145f2 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -1,4 +1,4 @@ -require 'active_support/core_ext/integer/time' +require "active_support/core_ext/integer/time" Rails.application.configure do # Settings specified here will take precedence over those in config/application.rb. @@ -14,19 +14,17 @@ Rails.application.configure do # Show full error reports. config.consider_all_requests_local = true - # Enable server timing + # Enable server timing. config.server_timing = true # Enable/disable caching. By default caching is disabled. # Run rails dev:cache to toggle caching. - if Rails.root.join('tmp/caching-dev.txt').exist? + if Rails.root.join("tmp/caching-dev.txt").exist? config.action_controller.perform_caching = true config.action_controller.enable_fragment_cache_logging = true config.cache_store = :memory_store - config.public_file_server.headers = { - 'Cache-Control' => "public, max-age=#{2.days.to_i}" - } + config.public_file_server.headers = { "Cache-Control" => "public, max-age=#{2.days.to_i}" } else config.action_controller.perform_caching = false @@ -39,8 +37,12 @@ Rails.application.configure do # Don't care if the mailer can't send. config.action_mailer.raise_delivery_errors = false + # Disable caching for Action Mailer templates even if Action Controller + # caching is enabled. config.action_mailer.perform_caching = false + config.action_mailer.default_url_options = { host: "a11yist.localhost" } + # Print deprecation notices to the Rails logger. config.active_support.deprecation = :log @@ -66,13 +68,16 @@ Rails.application.configure do # config.i18n.raise_on_missing_translations = true # Annotate rendered view with file names. - # config.action_view.annotate_rendered_view_with_filenames = true + config.action_view.annotate_rendered_view_with_filenames = true # Uncomment if you wish to allow Action Cable access from any origin. # config.action_cable.disable_request_forgery_protection = true - # Raise error when a before_action's only/except options reference missing actions + # Raise error when a before_action's only/except options reference missing actions. config.action_controller.raise_on_missing_callback_actions = true - config.web_console.permissions = ['192.168.0.0/16', '10.10.0.0/16'] + # Apply autocorrection by RuboCop to files generated by `bin/rails generate`. + # config.generators.apply_rubocop_autocorrect_after_generate! + # + config.web_console.allowed_ips = ["10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16", "127.0.0.0/8"] end diff --git a/config/environments/production.rb b/config/environments/production.rb index 569a1d8..b20131b 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -1,4 +1,4 @@ -require 'active_support/core_ext/integer/time' +require "active_support/core_ext/integer/time" Rails.application.configure do # Settings specified here will take precedence over those in config/application.rb. @@ -21,7 +21,7 @@ Rails.application.configure do # config.require_master_key = true # Disable serving static files from `public/`, relying on NGINX/Apache to do so instead. - # config.public_file_server.enabled = false + config.public_file_server.enabled = ENV.fetch("ASSETS_PATH") { nil }.nil? # Compress CSS using a preprocessor. # config.assets.css_compressor = :sass @@ -49,20 +49,25 @@ Rails.application.configure do # config.assume_ssl = true # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. - config.force_ssl = true + config.force_ssl = false + + # Skip http-to-https redirect for the default health check endpoint. + # config.ssl_options = { redirect: { exclude: ->(request) { request.path == "/up" } } } + + config.logger = ActiveSupport::TaggedLogging.new(ActiveSupport::Logger.new("log/#{Rails.env}.log")) # Log to STDOUT by default - config.logger = ActiveSupport::Logger.new(STDOUT) - .tap { |logger| logger.formatter = ::Logger::Formatter.new } - .then { |logger| ActiveSupport::TaggedLogging.new(logger) } + # config.logger = ActiveSupport::Logger.new(STDOUT) + # .tap { |logger| logger.formatter = ::Logger::Formatter.new } + # .then { |logger| ActiveSupport::TaggedLogging.new(logger) } # Prepend all log lines with the following tags. - config.log_tags = [:request_id] + config.log_tags = [ :request_id, :remote_ip ] # "info" includes generic and useful information about system operation, but avoids logging too much # information to avoid inadvertent exposure of personally identifiable information (PII). If you # want to log everything, set the level to "debug". - config.log_level = ENV.fetch('RAILS_LOG_LEVEL', 'info') + config.log_level = ENV.fetch("RAILS_LOG_LEVEL", "info") # Use a different cache store in production. # config.cache_store = :mem_cache_store @@ -71,6 +76,8 @@ Rails.application.configure do # config.active_job.queue_adapter = :resque # config.active_job.queue_name_prefix = "a11yist_production" + # Disable caching for Action Mailer templates even if Action Controller + # caching is enabled. config.action_mailer.perform_caching = false # Ignore bad email addresses and do not raise email delivery errors. @@ -92,8 +99,6 @@ Rails.application.configure do # "example.com", # Allow requests from example.com # /.*\.example\.com/ # Allow requests from subdomains like `www.example.com` # ] - config.hosts = ENV.fetch('APP_HOSTS', '').split(',') # Skip DNS rebinding protection for the default health check endpoint. # config.host_authorization = { exclude: ->(request) { request.path == "/up" } } - config.active_record.sqlite3_production_warning=false end diff --git a/config/environments/test.rb b/config/environments/test.rb index bb76f63..0c616a1 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -1,4 +1,4 @@ -require 'active_support/core_ext/integer/time' +require "active_support/core_ext/integer/time" # The test environment is used exclusively to run your application's # test suite. You never need to work with it otherwise. Remember that @@ -15,13 +15,10 @@ Rails.application.configure do # this is usually not necessary, and can slow down your test suite. However, it's # recommended that you enable it in continuous integration systems to ensure eager # loading is working properly before deploying your code. - config.eager_load = ENV['CI'].present? + config.eager_load = ENV["CI"].present? # Configure public file server for tests with Cache-Control for performance. - config.public_file_server.enabled = true - config.public_file_server.headers = { - 'Cache-Control' => "public, max-age=#{1.hour.to_i}" - } + config.public_file_server.headers = { "Cache-Control" => "public, max-age=#{1.hour.to_i}" } # Show full error reports and disable caching. config.consider_all_requests_local = true @@ -37,6 +34,8 @@ Rails.application.configure do # Store uploaded files on the local file system in a temporary directory. config.active_storage.service = :test + # Disable caching for Action Mailer templates even if Action Controller + # caching is enabled. config.action_mailer.perform_caching = false # Tell Action Mailer not to deliver emails to the real world. @@ -44,6 +43,10 @@ Rails.application.configure do # ActionMailer::Base.deliveries array. config.action_mailer.delivery_method = :test + # Unlike controllers, the mailer instance doesn't have any context about the + # incoming request so you'll need to provide the :host parameter yourself. + config.action_mailer.default_url_options = { host: "www.example.com" } + # Print deprecation notices to the stderr. config.active_support.deprecation = :stderr @@ -59,6 +62,6 @@ Rails.application.configure do # Annotate rendered view with file names. # config.action_view.annotate_rendered_view_with_filenames = true - # Raise error when a before_action's only/except options reference missing actions + # Raise error when a before_action's only/except options reference missing actions. config.action_controller.raise_on_missing_callback_actions = true end diff --git a/config/initializers/filter_parameter_logging.rb b/config/initializers/filter_parameter_logging.rb index 262e862..c010b83 100644 --- a/config/initializers/filter_parameter_logging.rb +++ b/config/initializers/filter_parameter_logging.rb @@ -3,6 +3,6 @@ # 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 += %i[ - passw secret token _key crypt salt certificate otp ssn +Rails.application.config.filter_parameters += [ + :passw, :email, :secret, :token, :_key, :crypt, :salt, :certificate, :otp, :ssn ] diff --git a/config/initializers/locale.rb b/config/initializers/locale.rb index 850ffb8..1b127cd 100644 --- a/config/initializers/locale.rb +++ b/config/initializers/locale.rb @@ -3,7 +3,7 @@ # I18n.load_path += Dir[Rails.root.join('lib', 'locale', '*.{rb,yml}')] # Permitted locales available for the application -I18n.available_locales = [:"de-CH"] +I18n.available_locales = [:"de-CH", :en] # Set default locale to something other than :en I18n.default_locale = :"de-CH" \ No newline at end of file diff --git a/config/initializers/new_framework_defaults_7_2.rb b/config/initializers/new_framework_defaults_7_2.rb new file mode 100644 index 0000000..53b5626 --- /dev/null +++ b/config/initializers/new_framework_defaults_7_2.rb @@ -0,0 +1,70 @@ +# Be sure to restart your server when you modify this file. +# +# This file eases your Rails 7.2 framework defaults upgrade. +# +# Uncomment each configuration one by one to switch to the new default. +# Once your application is ready to run with all new defaults, you can remove +# this file and set the `config.load_defaults` to `7.2`. +# +# Read the Guide for Upgrading Ruby on Rails for more info on each option. +# https://guides.rubyonrails.org/upgrading_ruby_on_rails.html + +### +# Controls whether Active Job's `#perform_later` and similar methods automatically defer +# the job queuing to after the current Active Record transaction is committed. +# +# Example: +# Topic.transaction do +# topic = Topic.create(...) +# NewTopicNotificationJob.perform_later(topic) +# end +# +# In this example, if the configuration is set to `:never`, the job will +# be enqueued immediately, even though the `Topic` hasn't been committed yet. +# Because of this, if the job is picked up almost immediately, or if the +# transaction doesn't succeed for some reason, the job will fail to find this +# topic in the database. +# +# If `enqueue_after_transaction_commit` is set to `:default`, the queue adapter +# will define the behaviour. +# +# Note: Active Job backends can disable this feature. This is generally done by +# backends that use the same database as Active Record as a queue, hence they +# don't need this feature. +#++ +# Rails.application.config.active_job.enqueue_after_transaction_commit = :default + +### +# Adds image/webp to the list of content types Active Storage considers as an image +# Prevents automatic conversion to a fallback PNG, and assumes clients support WebP, as they support gif, jpeg, and png. +# This is possible due to broad browser support for WebP, but older browsers and email clients may still not support +# WebP. Requires imagemagick/libvips built with WebP support. +#++ +Rails.application.config.active_storage.web_image_content_types = %w[image/png image/jpeg image/gif image/webp] + +### +# Enable validation of migration timestamps. When set, an ActiveRecord::InvalidMigrationTimestampError +# will be raised if the timestamp prefix for a migration is more than a day ahead of the timestamp +# associated with the current time. This is done to prevent forward-dating of migration files, which can +# impact migration generation and other migration commands. +# +# Applications with existing timestamped migrations that do not adhere to the +# expected format can disable validation by setting this config to `false`. +#++ +# Rails.application.config.active_record.validate_migration_timestamps = true + +### +# Controls whether the PostgresqlAdapter should decode dates automatically with manual queries. +# +# Example: +# ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.select_value("select '2024-01-01'::date") #=> Date +# +# This query used to return a `String`. +#++ +# Rails.application.config.active_record.postgresql_adapter_decode_dates = true + +### +# Enables YJIT as of Ruby 3.3, to bring sizeable performance improvements. If you are +# deploying to a memory constrained environment you may want to set this to `false`. +#++ +Rails.application.config.yjit = true diff --git a/config/locales/activerecord.yml b/config/locales/activerecord.yml index bf3043f..894aeb0 100644 --- a/config/locales/activerecord.yml +++ b/config/locales/activerecord.yml @@ -12,9 +12,39 @@ de-CH: results/not_applicable: Nicht anwendbar check: id: ID - level: Stufe + number: Nummer + external_number: WCAG Nummer + conformity_level: Konformitätsstufe position: Position - success_criterion_html: Erfolgskriterium + conformity_notice_de: Konformitätserklärung (de) + conformity_notice_en: Konformitätserklärung (eng) + standard_ids: Standards + name_de: Name (de) + name_en: Name (eng) + principle_id: Prinzip + priority: Priorität + quick_criterion_de: Quick Kriterium (de) + quick_criterion_en: Quick Kriterium (eng) + quick_fix_de: Quick Fix (de) + quick_fix_en: Quick Fix (eng) + quick_fail_de: Quick Fail (de) + quick_fail_en: Quick Fail (eng) + criterion_de: Kriterium/Grundlage (de) + criterion_en: Kriterium/Grundlage (eng) + criterion_details_de: Verstehen (de) + criterion_details_en: Verstehen (eng) + example_de: Beispiel (de) + example_en: Beispiel (eng) + exemption_details_de: Ausnahme (de) + exemption_details_en: Ausnahme (eng) + standard_text_de: WCAG-Text (de) + standard_text_en: WCAG-Text (eng) + test_instructions: Testanleitung + powerpoint_text_de: Powerpoint Text (de) + powerpoint_text_en: Powerpoint Text (eng) + comment: Kommentar + target_disability: Zugänglichkeit + applicability: Anwendbarkeit checklist: id: ID name: Überschrift @@ -65,3 +95,6 @@ de-CH: element: one: Element other: Elemente + principle: + one: Prinzip + other: Prinzipien diff --git a/config/locales/i11yist.yml b/config/locales/i11yist.yml index fc35e1c..a83f572 100644 --- a/config/locales/i11yist.yml +++ b/config/locales/i11yist.yml @@ -44,4 +44,17 @@ de-CH: link_show: "%{model} anzeigen" link_edit: "%{model} bearbeiten" link_destroy: "%{model} löschen" - link_index: "%{model} Liste" \ No newline at end of file + link_index: "%{model} Liste" + disability: + visual: visuell + auditory: auditiv + physical: motorisch + cognitive: kognitiv + applicability: + applicable_to_app: app + applicable_to_web: web + priority: + highest: "Sehr hoch" + high: "Hoch" + medium: "Mittel" + low: "Niedrig" \ No newline at end of file diff --git a/config/puma.rb b/config/puma.rb index 3b8d4f8..60e1b9c 100644 --- a/config/puma.rb +++ b/config/puma.rb @@ -2,34 +2,32 @@ # are invoked here are part of Puma's configuration DSL. For more information # about methods provided by the DSL, see https://puma.io/puma/Puma/DSL.html. -# 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. -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 - -# Specifies that the worker count should equal the number of processors in production. -if ENV['RAILS_ENV'] == 'production' - require 'concurrent-ruby' - worker_count = Integer(ENV.fetch('WEB_CONCURRENCY') { Concurrent.physical_processor_count }) - workers worker_count if worker_count > 1 -end - -# Specifies the `worker_timeout` threshold that Puma will use to wait before -# terminating a worker in development environments. -worker_timeout 3600 if ENV.fetch('RAILS_ENV', 'development') == 'development' +# Puma starts a configurable number of processes (workers) and each process +# serves each request in a thread from an internal thread pool. +# +# 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 `port` that Puma will listen on to receive requests; default is 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' } +port ENV.fetch("PORT", 3000) # Allow puma to be restarted by `bin/rails restart` command. plugin :tmp_restart + +# Only use a pidfile when requested +pidfile ENV["PIDFILE"] if ENV["PIDFILE"] diff --git a/config/routes.rb b/config/routes.rb index 4e10e3b..3f34a94 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -18,6 +18,21 @@ Rails.application.routes.draw do # Can be used by load balancers and uptime monitors to verify that the app is live. get 'up' => 'rails/health#show', as: :rails_health_check + if Rails.env.development? + namespace :benchmarking do + post "read_heavy" + post "write_heavy" + post "balanced" + post "link_create" + post "comment_create" + post "link_destroy" + post "comment_destroy" + post "link_show" + post "links_index" + post "user_show" + end + end + # Defines the root path route ("/") root 'home#show' end diff --git a/db/migrate/20240810081701_create_standards.rb b/db/migrate/20240810081701_create_standards.rb new file mode 100644 index 0000000..b1210c0 --- /dev/null +++ b/db/migrate/20240810081701_create_standards.rb @@ -0,0 +1,13 @@ +class CreateStandards < ActiveRecord::Migration[7.2] + def change + create_table :standards do |t| + t.string :name_de + t.string :name_en + t.string :version + t.string :url_de + t.string :url_en + + t.timestamps + end + end +end diff --git a/db/migrate/20240810185205_add_service_name_to_active_storage_blobs.active_storage.rb b/db/migrate/20240810185205_add_service_name_to_active_storage_blobs.active_storage.rb new file mode 100644 index 0000000..a15c6ce --- /dev/null +++ b/db/migrate/20240810185205_add_service_name_to_active_storage_blobs.active_storage.rb @@ -0,0 +1,22 @@ +# This migration comes from active_storage (originally 20190112182829) +class AddServiceNameToActiveStorageBlobs < ActiveRecord::Migration[6.0] + def up + return unless table_exists?(:active_storage_blobs) + + unless column_exists?(:active_storage_blobs, :service_name) + add_column :active_storage_blobs, :service_name, :string + + if configured_service = ActiveStorage::Blob.service.name + ActiveStorage::Blob.unscoped.update_all(service_name: configured_service) + end + + change_column :active_storage_blobs, :service_name, :string, null: false + end + end + + def down + return unless table_exists?(:active_storage_blobs) + + remove_column :active_storage_blobs, :service_name + end +end diff --git a/db/migrate/20240810185206_create_active_storage_variant_records.active_storage.rb b/db/migrate/20240810185206_create_active_storage_variant_records.active_storage.rb new file mode 100644 index 0000000..94ac83a --- /dev/null +++ b/db/migrate/20240810185206_create_active_storage_variant_records.active_storage.rb @@ -0,0 +1,27 @@ +# This migration comes from active_storage (originally 20191206030411) +class CreateActiveStorageVariantRecords < ActiveRecord::Migration[6.0] + def change + return unless table_exists?(:active_storage_blobs) + + # Use Active Record's configured type for primary key + create_table :active_storage_variant_records, id: primary_key_type, if_not_exists: true do |t| + t.belongs_to :blob, null: false, index: false, type: blobs_primary_key_type + t.string :variation_digest, null: false + + t.index %i[ blob_id variation_digest ], name: "index_active_storage_variant_records_uniqueness", unique: true + t.foreign_key :active_storage_blobs, column: :blob_id + end + end + + private + def primary_key_type + config = Rails.configuration.generators + config.options[config.orm][:primary_key_type] || :primary_key + end + + def blobs_primary_key_type + pkey_name = connection.primary_key(:active_storage_blobs) + pkey_column = connection.columns(:active_storage_blobs).find { |c| c.name == pkey_name } + pkey_column.bigint? ? :bigint : pkey_column.type + end +end diff --git a/db/migrate/20240810185207_remove_not_null_on_active_storage_blobs_checksum.active_storage.rb b/db/migrate/20240810185207_remove_not_null_on_active_storage_blobs_checksum.active_storage.rb new file mode 100644 index 0000000..93c8b85 --- /dev/null +++ b/db/migrate/20240810185207_remove_not_null_on_active_storage_blobs_checksum.active_storage.rb @@ -0,0 +1,8 @@ +# This migration comes from active_storage (originally 20211119233751) +class RemoveNotNullOnActiveStorageBlobsChecksum < ActiveRecord::Migration[6.0] + def change + return unless table_exists?(:active_storage_blobs) + + change_column_null(:active_storage_blobs, :checksum, true) + end +end diff --git a/db/migrate/20240819170606_create_principles.rb b/db/migrate/20240819170606_create_principles.rb new file mode 100644 index 0000000..04d2017 --- /dev/null +++ b/db/migrate/20240819170606_create_principles.rb @@ -0,0 +1,10 @@ +class CreatePrinciples < ActiveRecord::Migration[7.2] + def change + create_table :principles do |t| + t.string :name_de + t.string :name_en + + t.timestamps + end + end +end diff --git a/db/migrate/20240820164827_finalize_check_fields.rb b/db/migrate/20240820164827_finalize_check_fields.rb new file mode 100644 index 0000000..ceb0e27 --- /dev/null +++ b/db/migrate/20240820164827_finalize_check_fields.rb @@ -0,0 +1,26 @@ +class FinalizeCheckFields < ActiveRecord::Migration[7.2] + def change + add_column :checks, :number, :integer + add_index :checks, :number, unique: true + + add_column :checks, :name_de, :string + add_column :checks, :name_en, :string + + add_column :checks, :visual, :boolean, null: false, default: false + add_column :checks, :auditory, :boolean, null: false, default: false + add_column :checks, :physical, :boolean, null: false, default: false + add_column :checks, :cognitive, :boolean, null: false, default: false + + add_column :checks, :applicable_to_web, :boolean, null: false, default: false + add_column :checks, :applicable_to_app, :boolean, null: false, default: false + + add_reference :checks, :principle, foreign_key: true + + add_column :checks, :external_number, :string, null: true + add_column :checks, :conformity_level, :integer, null: false, default: 0 + add_column :checks, :priority, :integer, null: false, default: 0 + + add_column :checks, :manual_test, :boolean, null: false, default: true + add_column :checks, :test_url, :string, null: true + end +end diff --git a/db/migrate/20240830083327_add_checks_standards_join_table.rb b/db/migrate/20240830083327_add_checks_standards_join_table.rb new file mode 100644 index 0000000..c8548e4 --- /dev/null +++ b/db/migrate/20240830083327_add_checks_standards_join_table.rb @@ -0,0 +1,5 @@ +class AddChecksStandardsJoinTable < ActiveRecord::Migration[7.2] + def change + create_join_table :checks, :standards + end +end diff --git a/db/migrate/20240830134641_add_checks_links_join_table.rb b/db/migrate/20240830134641_add_checks_links_join_table.rb new file mode 100644 index 0000000..a62aa4d --- /dev/null +++ b/db/migrate/20240830134641_add_checks_links_join_table.rb @@ -0,0 +1,5 @@ +class AddChecksLinksJoinTable < ActiveRecord::Migration[7.2] + def change + create_join_table :checks, :links + end +end diff --git a/db/schema.rb b/db/schema.rb index 98809d5..7b21686 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.1].define(version: 2024_07_25_173433) do +ActiveRecord::Schema[7.2].define(version: 2024_08_30_134641) do create_table "action_text_rich_texts", force: :cascade do |t| t.string "name", null: false t.text "body" @@ -73,6 +73,36 @@ ActiveRecord::Schema[7.1].define(version: 2024_07_25_173433) do t.integer "level" t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.boolean "applicability_web", default: false, null: false + t.boolean "applicability_app", default: false, null: false + t.string "exernal_number" + t.integer "number" + t.string "name_de" + t.string "name_en" + t.boolean "visual", default: false, null: false + t.boolean "auditory", default: false, null: false + t.boolean "physical", default: false, null: false + t.boolean "cognitive", default: false, null: false + t.boolean "applicable_to_web", default: false, null: false + t.boolean "applicable_to_app", default: false, null: false + t.integer "principle_id" + t.string "external_number" + t.integer "conformity_level", default: 0, null: false + t.integer "priority", default: 0, null: false + t.boolean "manual_test", default: true, null: false + t.string "test_url" + t.index ["number"], name: "index_checks_on_number", unique: true + t.index ["principle_id"], name: "index_checks_on_principle_id" + end + + create_table "checks_links", id: false, force: :cascade do |t| + t.integer "check_id", null: false + t.integer "link_id", null: false + end + + create_table "checks_standards", id: false, force: :cascade do |t| + t.integer "check_id", null: false + t.integer "standard_id", null: false end create_table "elements", force: :cascade do |t| @@ -102,12 +132,29 @@ ActiveRecord::Schema[7.1].define(version: 2024_07_25_173433) do t.index ["link_category_id"], name: "index_links_on_link_category_id" end + create_table "principles", force: :cascade do |t| + t.string "name_de" + t.string "name_en" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + create_table "reports", force: :cascade do |t| t.string "name" t.datetime "created_at", null: false t.datetime "updated_at", null: false end + create_table "standards", force: :cascade do |t| + t.string "name_de" + t.string "name_en" + t.string "version" + t.string "url_de" + t.string "url_en" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + create_table "success_criteria", force: :cascade do |t| t.integer "element_id", null: false t.string "title" @@ -122,6 +169,7 @@ ActiveRecord::Schema[7.1].define(version: 2024_07_25_173433) do add_foreign_key "active_storage_variant_records", "active_storage_blobs", column: "blob_id" add_foreign_key "checklist_entries", "checklists" add_foreign_key "checklist_entries", "checks" + add_foreign_key "checks", "principles" add_foreign_key "elements", "reports" add_foreign_key "links", "link_categories" add_foreign_key "success_criteria", "elements" diff --git a/db/seeds.rb b/db/seeds.rb index 4fbd6ed..38c0424 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -1,9 +1,21 @@ -# This file should ensure the existence of records required to run the application in every environment (production, -# development, test). The code here should be idempotent so that it can be executed at any point in every environment. -# The data can then be loaded with the bin/rails db:seed command (or created alongside the database with db:setup). -# -# Example: -# -# ["Action", "Comedy", "Drama", "Horror"].each do |genre_name| -# MovieGenre.find_or_create_by!(name: genre_name) -# end +# Seed Standards +Standard.create!(name_de: "WCAG", + name_en: "WCAG", + version: "2.1", + url_de: "https://outline-rocks.github.io/wcag/translations/WCAG21-de/", + url_en: "https://www.w3.org/TR/WCAG21/") +Standard.create!(name_de: "eCH-0059", + name_en: "eCH-0059", + version: "3.0", + url_de: "https://www.ech.ch/de/ech/ech-0059/3.0", + url_en: "https://www.ech.ch/de/ech/ech-0059/3.0") +Standard.create!(name_de: "EN 301 549", + name_en: "EN 301 549", + version: "V3", + url_de: "https://www.etsi.org/deliver/etsi_en/301500_301599/301549/03.02.01_60/en_301549v030201p.pdf", + url_en: "https://www.etsi.org/deliver/etsi_en/301500_301599/301549/03.02.01_60/en_301549v030201p.pdf") + +Principle.create!(name_de: "Wahrnehmbar", name_en: "Perceivable") +Principle.create!(name_de: "Bedienbar", name_en: "Operable") +Principle.create!(name_de: "Verständlich", name_en: "Understandable") +Principle.create!(name_de: "Robust", name_en: "Robust") \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 877ee78..769d603 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -14,7 +14,7 @@ services: - ./:/app:cached - ${PWD}:${PWD} - ${HOME}/.tabby-client:/home/app/.tabby-client - working_dir: ${PWD} + - ${SSH_AUTH_SOCK}:/ssh-agent environment: RAILS_ENV: development LOG_LEVEL: debug diff --git a/lib/tasks/import.rake b/lib/tasks/import.rake index 44f95cf..3e14078 100644 --- a/lib/tasks/import.rake +++ b/lib/tasks/import.rake @@ -1,7 +1,9 @@ +# frozen_string_literal: true + namespace :import do - desc 'Import WCAG2.1 in german' + desc "Import WCAG2.1 in german" task wcag21de: :environment do - URL = 'https://outline-rocks.github.io/wcag/translations/WCAG21-de/' + URL = "https://outline-rocks.github.io/wcag/translations/WCAG21-de/" doc = Nokogiri::HTML5(URI.open(URL)) @@ -10,19 +12,19 @@ namespace :import do # standard.description = doc.css('#abstract p').map(&:to_s).join # standard.save! - doc.css('section.principle').each do |principle_node| - _principle_id = principle_node.attributes['id'].value - _principle_title = principle_node.css('h2').first.content + doc.css("section.principle").each do |principle_node| + _principle_id = principle_node.attributes["id"].value + _principle_title = principle_node.css("h2").first.content # principle = standard.principles.find_or_create_by(code: principle_id) # principle.name = principle_title.scan(/\d+\. (.*)/).first.last # principle.number = principle_title.scan(/(\d+)\..*/).first.last # principle.save! - principle_node.css('section').each do |guideline_node| - next unless guideline_node.css('h3').first + principle_node.css("section").each do |guideline_node| + next unless guideline_node.css("h3").first - guideline_title = guideline_node.css('h3').first.content - guideline_text = guideline_node.css('p').first + guideline_title = guideline_node.css("h3").first.content + guideline_text = guideline_node.css("p").first _guideline_number = guideline_title.scan(/Richtlinie \d+\.(\d+).*/).first.last # guideline = principle.guidelines.find_or_create_by(number: guideline_number) @@ -31,9 +33,9 @@ namespace :import do # guideline.save! - guideline_node.css('section').each do |sc| - sc_title = sc.css('h4').first.content.scan(/Erfolgskriterium \d+\.\d+\.\d+(.*)/).first.last - sc_level = sc.css('p').first.content.scan(/\(Stufe (A+)\)/).first.last + guideline_node.css("section").each do |sc| + sc_title = sc.css("h4").first.content.scan(/Erfolgskriterium \d+\.\d+\.\d+(.*)/).first.last + sc_level = sc.css("p").first.content.scan(/\(Stufe (A+)\)/).first.last # sc_hints = sc.css('div p').map { ReverseMarkdown.convert(_1.to_s) } # _sc_number = sc_title.scan(/Erfolgskriterium \d+\.\d+\.(\d+).*/).first.last @@ -41,7 +43,7 @@ namespace :import do success_criterion = Check.find_or_create_by(name: sc_title) success_criterion.name = sc_title text = "
#{guideline_text}
#{sc.css('p')[1]}" - text += "

#{sc.css('dl').first&.to_s}

" if sc.css('dl').first + text += "

#{sc.css('dl').first&.to_s}

" if sc.css("dl").first success_criterion.success_criterion_html = "#{text}
".gsub('href="#', %(href="#{URL}#)) success_criterion.level = sc_level diff --git a/public/406-unsupported-browser.html b/public/406-unsupported-browser.html new file mode 100644 index 0000000..7cf1e16 --- /dev/null +++ b/public/406-unsupported-browser.html @@ -0,0 +1,66 @@ + + + + Your browser is not supported (406) + + + + + + +
+
+

Your browser is not supported.

+

Please upgrade your browser to continue.

+
+
+ + diff --git a/public/icon.png b/public/icon.png new file mode 100644 index 0000000..f3b5abc Binary files /dev/null and b/public/icon.png differ diff --git a/public/icon.svg b/public/icon.svg new file mode 100644 index 0000000..78307cc --- /dev/null +++ b/public/icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/test/application_system_test_case.rb b/test/application_system_test_case.rb index 375c1ab..bc7bf46 100644 --- a/test/application_system_test_case.rb +++ b/test/application_system_test_case.rb @@ -1,14 +1,15 @@ # frozen_string_literal: true -require 'test_helper' +require "test_helper" class ApplicationSystemTestCase < ActionDispatch::SystemTestCase driven_by(:selenium, using: :headless_chrome, - options: { browser: :remote, url: ENV.fetch('SELENIUM_REMOTE_URL', nil) }) + options: { browser: :remote, + url: ENV.fetch("SELENIUM_REMOTE_URL", nil) }) def setup - Capybara.server_host = '0.0.0.0' # bind to all interfaces - Capybara.app_host = "http://#{IPSocket.getaddress(Socket.gethostname)}" if ENV['SELENIUM_REMOTE_URL'].present? + Capybara.server_host = "0.0.0.0" # bind to all interfaces + Capybara.app_host = "http://#{IPSocket.getaddress(Socket.gethostname)}" if ENV["SELENIUM_REMOTE_URL"].present? super end diff --git a/test/channels/application_cable/connection_test.rb b/test/channels/application_cable/connection_test.rb index 4aee9b3..baa2e3f 100644 --- a/test/channels/application_cable/connection_test.rb +++ b/test/channels/application_cable/connection_test.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'test_helper' +require "test_helper" module ApplicationCable class ConnectionTest < ActionCable::Connection::TestCase diff --git a/test/controllers/admin/backups_controller_test.rb b/test/controllers/admin/backups_controller_test.rb index 7e5ef21..3cca198 100644 --- a/test/controllers/admin/backups_controller_test.rb +++ b/test/controllers/admin/backups_controller_test.rb @@ -1,8 +1,12 @@ -require 'test_helper' +# frozen_string_literal: true -class Admin::BackupsControllerTest < ActionDispatch::IntegrationTest - test 'should show admin_backup' do - get admin_backup_url(@admin_backup) - assert_response :success +require "test_helper" + +module Admin + class BackupsControllerTest < ActionDispatch::IntegrationTest + test "should show admin_backup" do + get admin_backup_url(@admin_backup) + assert_response :success + end end end diff --git a/test/controllers/checklist_entries_controller_test.rb b/test/controllers/checklist_entries_controller_test.rb index a5219c4..fc21961 100644 --- a/test/controllers/checklist_entries_controller_test.rb +++ b/test/controllers/checklist_entries_controller_test.rb @@ -1,22 +1,24 @@ -require 'test_helper' +# frozen_string_literal: true + +require "test_helper" class ChecklistEntriesControllerTest < ActionDispatch::IntegrationTest setup do @checklist_entry = checklist_entries(:one) end - test 'should get index' do + test "should get index" do get checklist_entries_url assert_response :success end - test 'should get new' do + test "should get new" do get new_checklist_entry_url(checklist_id: @checklist_entry.checklist_id) assert_response :success end - test 'should create checklist_entry' do - assert_difference('ChecklistEntry.count') do + test "should create checklist_entry" do + assert_difference("ChecklistEntry.count") do post checklist_entries_url, params: { checklist_entry: { check_id: @checklist_entry.check_id, checklist_id: @checklist_entry.checklist_id, position: @checklist_entry.position } } @@ -25,25 +27,25 @@ class ChecklistEntriesControllerTest < ActionDispatch::IntegrationTest assert_redirected_to checklist_url(ChecklistEntry.last.checklist) end - test 'should show checklist_entry' do + test "should show checklist_entry" do get checklist_entry_url(@checklist_entry) assert_response :success end - test 'should get edit' do + test "should get edit" do get edit_checklist_entry_url(@checklist_entry) assert_response :success end - test 'should update checklist_entry' do + test "should update checklist_entry" do patch checklist_entry_url(@checklist_entry), params: { checklist_entry: { check_id: @checklist_entry.check_id, checklist_id: @checklist_entry.checklist_id, position: @checklist_entry.position } } assert_redirected_to checklist_url(@checklist_entry.checklist) end - test 'should destroy checklist_entry' do - assert_difference('ChecklistEntry.count', -1) do + test "should destroy checklist_entry" do + assert_difference("ChecklistEntry.count", -1) do delete checklist_entry_url(@checklist_entry) end diff --git a/test/controllers/checklists_controller_test.rb b/test/controllers/checklists_controller_test.rb index dcfe1b7..6fdaf63 100644 --- a/test/controllers/checklists_controller_test.rb +++ b/test/controllers/checklists_controller_test.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "test_helper" class ChecklistsControllerTest < ActionDispatch::IntegrationTest @@ -17,7 +19,9 @@ class ChecklistsControllerTest < ActionDispatch::IntegrationTest test "should create checklist" do assert_difference("Checklist.count") do - post checklists_url, params: { checklist: { code: @checklist.code, description_html: @checklist.description_html, name: @checklist.name } } + post checklists_url, + params: { checklist: { code: @checklist.code, description_html: @checklist.description_html, + name: @checklist.name } } end assert_redirected_to checklist_url(Checklist.last) @@ -34,7 +38,9 @@ class ChecklistsControllerTest < ActionDispatch::IntegrationTest end test "should update checklist" do - patch checklist_url(@checklist), params: { checklist: { code: @checklist.code, description_html: @checklist.description_html, name: @checklist.name } } + patch checklist_url(@checklist), + params: { checklist: { code: @checklist.code, description_html: @checklist.description_html, + name: @checklist.name } } assert_redirected_to checklist_url(@checklist) end diff --git a/test/controllers/checks_controller_test.rb b/test/controllers/checks_controller_test.rb index 6e110ac..4b3e44e 100644 --- a/test/controllers/checks_controller_test.rb +++ b/test/controllers/checks_controller_test.rb @@ -1,49 +1,52 @@ -require 'test_helper' +# frozen_string_literal: true + +require "test_helper" class ChecksControllerTest < ActionDispatch::IntegrationTest setup do + @principle = principles(:one) @check = checks(:deletable) end - test 'should get index' do + test "should get index" do get checks_url assert_response :success end - test 'should get new' do + test "should get new" do get new_check_url assert_response :success end - test 'should create check' do - assert_difference('Check.count') do + test "should create check" do + assert_difference("Check.count") do post checks_url, - params: { check: { level: @check.level, name: @check.name, position: @check.position, - success_criterion_html: @check.success_criterion_html } } + params: { check: { principle_id: @principle.id, level: @check.level, name_de: @check.name_de, position: @check.position, + criterion_de: @check.criterion_de } } end assert_redirected_to check_url(Check.last) end - test 'should show check' do + test "should show check" do get check_url(@check) assert_response :success end - test 'should get edit' do + test "should get edit" do get edit_check_url(@check) assert_response :success end - test 'should update check' do + test "should update check" do patch check_url(@check), - params: { check: { level: @check.level, name: @check.name, position: @check.position, - success_criterion_html: @check.success_criterion_html } } + params: { check: { principle_id: @principle.id, level: @check.level, name_de: @check.t_name, position: @check.position, + criterion_de: @check.criterion_de } } assert_redirected_to check_url(@check) end - test 'should destroy check' do - assert_difference('Check.count', -1) do + test "should destroy check" do + assert_difference("Check.count", -1) do delete check_url(@check) end diff --git a/test/controllers/elements_controller_test.rb b/test/controllers/elements_controller_test.rb index 9d34716..f31c589 100644 --- a/test/controllers/elements_controller_test.rb +++ b/test/controllers/elements_controller_test.rb @@ -1,4 +1,6 @@ -require 'test_helper' +# frozen_string_literal: true + +require "test_helper" class ElementsControllerTest < ActionDispatch::IntegrationTest setup do @@ -6,18 +8,18 @@ class ElementsControllerTest < ActionDispatch::IntegrationTest @checklist = checklists(:one) end - test 'should get index' do + test "should get index" do get elements_url assert_response :success end - test 'should get new' do + test "should get new" do get new_element_url assert_response :success end - test 'should create element' do - assert_difference('Element.count') do + test "should create element" do + assert_difference("Element.count") do post elements_url, params: { element: { description_html: @element.description_html, path: @element.path, report_id: @element.report_id, title: @element.title, checklist_id: @checklist.id } } @@ -26,25 +28,25 @@ class ElementsControllerTest < ActionDispatch::IntegrationTest assert_redirected_to report_url(Element.last.report) end - test 'should show element' do + test "should show element" do get element_url(@element) assert_response :success end - test 'should get edit' do + test "should get edit" do get edit_element_url(@element) assert_response :success end - test 'should update element' do + test "should update element" do patch element_url(@element), params: { element: { description_html: @element.description_html, path: @element.path, report_id: @element.report_id, title: @element.title } } assert_redirected_to element_url(@element) end - test 'should destroy element' do - assert_difference('Element.count', -1) do + test "should destroy element" do + assert_difference("Element.count", -1) do delete element_url(@element) end diff --git a/test/controllers/home_controller_test.rb b/test/controllers/home_controller_test.rb index 5f4cb7b..28297fc 100644 --- a/test/controllers/home_controller_test.rb +++ b/test/controllers/home_controller_test.rb @@ -1,9 +1,9 @@ # frozen_string_literal: true -require 'test_helper' +require "test_helper" class HomeControllerTest < ActionDispatch::IntegrationTest - test 'should get show' do + test "should get show" do get root_url assert_response :success end diff --git a/test/controllers/link_categories_controller_test.rb b/test/controllers/link_categories_controller_test.rb index 99829d7..5dc7ab1 100644 --- a/test/controllers/link_categories_controller_test.rb +++ b/test/controllers/link_categories_controller_test.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "test_helper" class LinkCategoriesControllerTest < ActionDispatch::IntegrationTest @@ -17,7 +19,8 @@ class LinkCategoriesControllerTest < ActionDispatch::IntegrationTest test "should create link_category" do assert_difference("LinkCategory.count") do - post link_categories_url, params: { link_category: { description: @link_category.description, name: @link_category.name } } + post link_categories_url, + params: { link_category: { description: @link_category.description, name: @link_category.name } } end assert_redirected_to link_category_url(LinkCategory.last) @@ -34,7 +37,8 @@ class LinkCategoriesControllerTest < ActionDispatch::IntegrationTest end test "should update link_category" do - patch link_category_url(@link_category), params: { link_category: { description: @link_category.description, name: @link_category.name } } + patch link_category_url(@link_category), + params: { link_category: { description: @link_category.description, name: @link_category.name } } assert_redirected_to link_category_url(@link_category) end diff --git a/test/controllers/links_controller_test.rb b/test/controllers/links_controller_test.rb index 3c83334..a2ebc27 100644 --- a/test/controllers/links_controller_test.rb +++ b/test/controllers/links_controller_test.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "test_helper" class LinksControllerTest < ActionDispatch::IntegrationTest @@ -17,7 +19,9 @@ class LinksControllerTest < ActionDispatch::IntegrationTest test "should create link" do assert_difference("Link.count") do - post links_url, params: { link: { fail_count: @link.fail_count, last_check_at: @link.last_check_at, link_category_id: @link.link_category_id, text: @link.text, url: @link.url } } + post links_url, + params: { link: { fail_count: @link.fail_count, last_check_at: @link.last_check_at, + link_category_id: @link.link_category_id, text: @link.text, url: @link.url } } end assert_redirected_to link_url(Link.last) @@ -34,7 +38,9 @@ class LinksControllerTest < ActionDispatch::IntegrationTest end test "should update link" do - patch link_url(@link), params: { link: { fail_count: @link.fail_count, last_check_at: @link.last_check_at, link_category_id: @link.link_category_id, text: @link.text, url: @link.url } } + patch link_url(@link), + params: { link: { fail_count: @link.fail_count, last_check_at: @link.last_check_at, + link_category_id: @link.link_category_id, text: @link.text, url: @link.url } } assert_redirected_to link_url(@link) end diff --git a/test/controllers/reports_controller_test.rb b/test/controllers/reports_controller_test.rb index 6e26f15..b2e5c8d 100644 --- a/test/controllers/reports_controller_test.rb +++ b/test/controllers/reports_controller_test.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "test_helper" class ReportsControllerTest < ActionDispatch::IntegrationTest diff --git a/test/controllers/success_criteria_controller_test.rb b/test/controllers/success_criteria_controller_test.rb index 3046632..78d7954 100644 --- a/test/controllers/success_criteria_controller_test.rb +++ b/test/controllers/success_criteria_controller_test.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "test_helper" class SuccessCriteriaControllerTest < ActionDispatch::IntegrationTest @@ -17,7 +19,9 @@ class SuccessCriteriaControllerTest < ActionDispatch::IntegrationTest test "should create success_criterion" do assert_difference("SuccessCriterion.count") do - post success_criteria_url, params: { success_criterion: { comment_html: @success_criterion.comment_html, description_html: @success_criterion.description_html, element_id: @success_criterion.element_id, level: @success_criterion.level, result: @success_criterion.result, title: @success_criterion.title } } + post success_criteria_url, + params: { success_criterion: { comment_html: @success_criterion.comment_html, + description_html: @success_criterion.description_html, element_id: @success_criterion.element_id, level: @success_criterion.level, result: @success_criterion.result, title: @success_criterion.title } } end assert_redirected_to success_criterion_url(SuccessCriterion.last) @@ -34,7 +38,9 @@ class SuccessCriteriaControllerTest < ActionDispatch::IntegrationTest end test "should update success_criterion" do - patch success_criterion_url(@success_criterion), params: { success_criterion: { comment_html: @success_criterion.comment_html, description_html: @success_criterion.description_html, element_id: @success_criterion.element_id, level: @success_criterion.level, result: @success_criterion.result, title: @success_criterion.title } } + patch success_criterion_url(@success_criterion), + params: { success_criterion: { comment_html: @success_criterion.comment_html, + description_html: @success_criterion.description_html, element_id: @success_criterion.element_id, level: @success_criterion.level, result: @success_criterion.result, title: @success_criterion.title } } assert_redirected_to success_criterion_url(@success_criterion) end diff --git a/test/fixtures/principles.yml b/test/fixtures/principles.yml new file mode 100644 index 0000000..fdf7fe6 --- /dev/null +++ b/test/fixtures/principles.yml @@ -0,0 +1,9 @@ +# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +one: + name_de: MyString + name_en: MyString + +two: + name_de: MyString + name_en: MyString diff --git a/test/fixtures/standards.yml b/test/fixtures/standards.yml new file mode 100644 index 0000000..08c1bea --- /dev/null +++ b/test/fixtures/standards.yml @@ -0,0 +1,15 @@ +# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +one: + name_de: MyString + name_en: MyString + version: MyString + url_de: MyString + url_en: MyString + +two: + name_de: MyString + name_en: MyString + version: MyString + url_de: MyString + url_en: MyString diff --git a/test/models/check_test.rb b/test/models/check_test.rb index fc18f2b..d2b0b5e 100644 --- a/test/models/check_test.rb +++ b/test/models/check_test.rb @@ -1,8 +1,10 @@ -require 'test_helper' +# frozen_string_literal: true + +require "test_helper" class CheckTest < ActiveSupport::TestCase - test 'the truth' do - skip 'Need to write Check test' + test "the truth" do + skip "Need to write Check test" assert true end end diff --git a/test/models/checklist_entry_test.rb b/test/models/checklist_entry_test.rb index 740c6e5..f4f2826 100644 --- a/test/models/checklist_entry_test.rb +++ b/test/models/checklist_entry_test.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "test_helper" class ChecklistEntryTest < ActiveSupport::TestCase diff --git a/test/models/checklist_test.rb b/test/models/checklist_test.rb index 4728cb3..512d5fc 100644 --- a/test/models/checklist_test.rb +++ b/test/models/checklist_test.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "test_helper" class ChecklistTest < ActiveSupport::TestCase diff --git a/test/models/element_test.rb b/test/models/element_test.rb index 62026f9..5c426c6 100644 --- a/test/models/element_test.rb +++ b/test/models/element_test.rb @@ -1,10 +1,12 @@ -require 'test_helper' +# frozen_string_literal: true + +require "test_helper" class ElementTest < ActiveSupport::TestCase # test "the truth" do # assert true # end - test 'level calculation' do + test "level calculation" do skip sc1 = success_criteria(:one) sc2 = success_criteria(:two) @@ -13,12 +15,12 @@ class ElementTest < ActiveSupport::TestCase sc5 = success_criteria(:one) sc6 = success_criteria(:two) element = elements(:one) - element.success_criteria = [sc1, sc2, sc3, sc4, sc5, sc6] - element.success_criteria.each { _1.passed! } + element.success_criteria = [ sc1, sc2, sc3, sc4, sc5, sc6 ] + element.success_criteria.each(&:passed!) assert element.level == :A element.success_criteria.each { _1.result = :passed } - assert element.level == 'A' + assert element.level == "A" end end diff --git a/test/models/link_category_test.rb b/test/models/link_category_test.rb index f47575f..9fd921d 100644 --- a/test/models/link_category_test.rb +++ b/test/models/link_category_test.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "test_helper" class LinkCategoryTest < ActiveSupport::TestCase diff --git a/test/models/link_test.rb b/test/models/link_test.rb index c4a0f6e..01be32c 100644 --- a/test/models/link_test.rb +++ b/test/models/link_test.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "test_helper" class LinkTest < ActiveSupport::TestCase diff --git a/test/models/principle_test.rb b/test/models/principle_test.rb new file mode 100644 index 0000000..1898b02 --- /dev/null +++ b/test/models/principle_test.rb @@ -0,0 +1,7 @@ +require "test_helper" + +class PrincipleTest < ActiveSupport::TestCase + # test "the truth" do + # assert true + # end +end diff --git a/test/models/report_test.rb b/test/models/report_test.rb index 600b075..d7e6d7a 100644 --- a/test/models/report_test.rb +++ b/test/models/report_test.rb @@ -1,7 +1,9 @@ -require 'test_helper' +# frozen_string_literal: true + +require "test_helper" class ReportTest < ActiveSupport::TestCase - test 'the truth' do + test "the truth" do assert_not Report.new.valid? end end diff --git a/test/models/standard_test.rb b/test/models/standard_test.rb new file mode 100644 index 0000000..7a1ec47 --- /dev/null +++ b/test/models/standard_test.rb @@ -0,0 +1,7 @@ +require "test_helper" + +class StandardTest < ActiveSupport::TestCase + # test "the truth" do + # assert true + # end +end diff --git a/test/models/success_criterion_test.rb b/test/models/success_criterion_test.rb index d0769b2..fb8526e 100644 --- a/test/models/success_criterion_test.rb +++ b/test/models/success_criterion_test.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "test_helper" class SuccessCriterionTest < ActiveSupport::TestCase diff --git a/test/system/admin/backups_test.rb b/test/system/admin/backups_test.rb index 3cc9dd1..437c6c5 100644 --- a/test/system/admin/backups_test.rb +++ b/test/system/admin/backups_test.rb @@ -1,7 +1,11 @@ -require 'application_system_test_case' +# frozen_string_literal: true -class Admin::BackupsTest < ApplicationSystemTestCase - test 'should create backup' do - visit admin_backup_url +require "application_system_test_case" + +module Admin + class BackupsTest < ApplicationSystemTestCase + test "should create backup" do + visit admin_backup_url + end end end diff --git a/test/system/checklists_test.rb b/test/system/checklists_test.rb index 18f9ca0..a1b4af6 100644 --- a/test/system/checklists_test.rb +++ b/test/system/checklists_test.rb @@ -1,35 +1,37 @@ -require 'application_system_test_case' +# frozen_string_literal: true + +require "application_system_test_case" class ChecklistsTest < ApplicationSystemTestCase setup do @checklist = checklists(:one) end - test 'visiting the index' do + test "visiting the index" do visit checklists_url - assert_selector 'h1', text: 'Checklisten' + assert_selector "h1", text: "Checklisten" end - test 'should create checklist' do + test "should create checklist" do visit checklists_url - click_on 'Checkliste hinzufügen' + click_on "Checkliste hinzufügen" - fill_in_rich_text_area 'Details', with: @checklist.description_html - fill_in 'Überschrift', with: @checklist.name - click_on 'Checkliste erstellen' + fill_in_rich_text_area "Details", with: @checklist.description_html + fill_in "Überschrift", with: @checklist.name + click_on "Checkliste erstellen" end - test 'should update Checkliste' do + test "should update Checkliste" do visit checklist_url(@checklist) - click_on 'Checkliste bearbeiten', match: :first + click_on "Checkliste bearbeiten", match: :first - fill_in_rich_text_area 'Details', with: @checklist.description_html - fill_in 'Überschrift', with: @checklist.name - click_on 'Checkliste aktualisieren' + fill_in_rich_text_area "Details", with: @checklist.description_html + fill_in "Überschrift", with: @checklist.name + click_on "Checkliste aktualisieren" end - test 'should destroy Checkliste' do + test "should destroy Checkliste" do visit checklist_url(@checklist) - click_on 'Checkliste löschen', match: :first + click_on "Checkliste löschen", match: :first end end diff --git a/test/system/checks_test.rb b/test/system/checks_test.rb index 5c2b097..5e3a3ea 100644 --- a/test/system/checks_test.rb +++ b/test/system/checks_test.rb @@ -1,4 +1,6 @@ -require 'application_system_test_case' +# frozen_string_literal: true + +require "application_system_test_case" class ChecksTest < ApplicationSystemTestCase setup do @@ -6,39 +8,39 @@ class ChecksTest < ApplicationSystemTestCase @deletable_check = checks(:deletable) end - test 'visiting the index' do + test "visiting the index" do visit checks_url - assert_selector 'h1', text: 'Checks' + assert_selector "h1", text: "Checks" end - test 'should create check' do + test "should create check" do visit checks_url - click_on 'Check hinzufügen' + click_on "Check hinzufügen" - select 'AAA', from: 'Stufe' - fill_in 'Name', with: @check.name - fill_in 'Position', with: @check.position - fill_in_rich_text_area 'Erfolgskriterium', with: @check.success_criterion_html - click_on 'Check erstellen' + select "AAA", from: "Stufe" + fill_in "Name", with: @check.name + fill_in "Position", with: @check.position + fill_in_rich_text_area "Erfolgskriterium", with: @check.success_criterion_html + click_on "Check erstellen" end - test 'should update Check' do + test "should update Check" do visit check_url(@check) - click_on 'Check bearbeiten', match: :first + click_on "Check bearbeiten", match: :first - select 'AAA', from: 'Stufe' - fill_in 'Name', with: @check.name - fill_in 'Position', with: @check.position - fill_in_rich_text_area 'Erfolgskriterium', with: @check.success_criterion_html - click_on 'Check aktualisieren' + select "AAA", from: "Stufe" + fill_in "Name", with: @check.name + fill_in "Position", with: @check.position + fill_in_rich_text_area "Erfolgskriterium", with: @check.success_criterion_html + click_on "Check aktualisieren" end - test 'should destroy Check' do + test "should destroy Check" do visit check_url(@deletable_check) - click_on 'Check löschen', match: :first + click_on "Check löschen", match: :first end - test 'fail' do + test "fail" do skip assert false end diff --git a/test/system/elements_test.rb b/test/system/elements_test.rb index ef8b5e2..509b244 100644 --- a/test/system/elements_test.rb +++ b/test/system/elements_test.rb @@ -1,37 +1,39 @@ -require 'application_system_test_case' +# frozen_string_literal: true + +require "application_system_test_case" class ElementsTest < ApplicationSystemTestCase setup do @element = elements(:one) end - test 'visiting the index' do + test "visiting the index" do visit elements_url - assert_selector 'h1', text: 'Elemente' + assert_selector "h1", text: "Elemente" end - test 'should create element' do + test "should create element" do visit elements_url - click_on 'Element hinzufügen' + click_on "Element hinzufügen" - fill_in_rich_text_area 'Details', with: @element.description_html - fill_in 'Pfad', with: @element.path - fill_in 'Beschreibung', with: @element.title - click_on 'Element erstellen' + fill_in_rich_text_area "Details", with: @element.description_html + fill_in "Pfad", with: @element.path + fill_in "Beschreibung", with: @element.title + click_on "Element erstellen" end - test 'should update Element' do + test "should update Element" do visit element_url(@element) - click_on 'Element bearbeiten', match: :first + click_on "Element bearbeiten", match: :first - fill_in_rich_text_area 'Details', with: @element.description_html - fill_in 'Pfad', with: @element.path - fill_in 'Beschreibung', with: @element.title - click_on 'Element aktualisieren' + fill_in_rich_text_area "Details", with: @element.description_html + fill_in "Pfad", with: @element.path + fill_in "Beschreibung", with: @element.title + click_on "Element aktualisieren" end - test 'should destroy Element' do + test "should destroy Element" do visit element_url(@element) - click_on 'Element löschen', match: :first + click_on "Element löschen", match: :first end end diff --git a/test/system/link_categories_test.rb b/test/system/link_categories_test.rb index 7dfd499..b36ca10 100644 --- a/test/system/link_categories_test.rb +++ b/test/system/link_categories_test.rb @@ -1,36 +1,38 @@ -require 'application_system_test_case' +# frozen_string_literal: true + +require "application_system_test_case" class LinkCategoriesTest < ApplicationSystemTestCase setup do @link_category = link_categories(:one) end - test 'visiting the index' do + test "visiting the index" do visit link_categories_url - assert_selector 'h1', text: 'Linkkategorien' + assert_selector "h1", text: "Linkkategorien" end - test 'should create Linkkategorie' do + test "should create Linkkategorie" do visit link_categories_url - click_on 'Linkkategorie hinzufügen' + click_on "Linkkategorie hinzufügen" - fill_in_rich_text_area 'Beschreibung', with: @link_category.description_html - fill_in 'Name', with: @link_category.name - click_on 'Linkkategorie erstellen' + fill_in_rich_text_area "Beschreibung", with: @link_category.description_html + fill_in "Name", with: @link_category.name + click_on "Linkkategorie erstellen" end - test 'should update Link category' do + test "should update Link category" do visit link_category_url(@link_category) - click_on 'Linkkategorie bearbeiten', match: :first + click_on "Linkkategorie bearbeiten", match: :first - fill_in_rich_text_area 'Beschreibung', with: @link_category.description_html - fill_in 'Name', with: @link_category.name - click_on 'Linkkategorie aktualisieren' + fill_in_rich_text_area "Beschreibung", with: @link_category.description_html + fill_in "Name", with: @link_category.name + click_on "Linkkategorie aktualisieren" end - test 'should destroy Link category' do + test "should destroy Link category" do link_category = link_categories(:deletable) visit link_category_url(link_category) - click_on 'Linkkategorie löschen', match: :first + click_on "Linkkategorie löschen", match: :first end end diff --git a/test/system/links_test.rb b/test/system/links_test.rb index 0b7acd9..5802167 100644 --- a/test/system/links_test.rb +++ b/test/system/links_test.rb @@ -1,37 +1,39 @@ -require 'application_system_test_case' +# frozen_string_literal: true + +require "application_system_test_case" class LinksTest < ApplicationSystemTestCase setup do @link = links(:one) end - test 'visiting the index' do + test "visiting the index" do visit links_url - assert_selector 'h1', text: 'Links' + assert_selector "h1", text: "Links" end - test 'should create link' do + test "should create link" do visit links_url - click_on 'Link hinzufügen' + click_on "Link hinzufügen" - select @link.link_category.name, from: 'Kategorie' - fill_in 'Linktext', with: @link.text - fill_in 'Link', with: @link.url - click_on 'Link erstellen' + select @link.link_category.name, from: "Kategorie" + fill_in "Linktext", with: @link.text + fill_in "Link", with: @link.url + click_on "Link erstellen" end - test 'should update Link' do + test "should update Link" do visit link_url(@link) - click_on 'Link bearbeiten', match: :first + click_on "Link bearbeiten", match: :first - select @link.link_category.name, from: 'Kategorie' - fill_in 'Linktext', with: @link.text - fill_in 'Link', with: @link.url - click_on 'Link aktualisieren' + select @link.link_category.name, from: "Kategorie" + fill_in "Linktext", with: @link.text + fill_in "Link", with: @link.url + click_on "Link aktualisieren" end - test 'should destroy Link' do + test "should destroy Link" do visit link_url(@link) - click_on 'Link löschen', match: :first + click_on "Link löschen", match: :first end end diff --git a/test/system/reports_test.rb b/test/system/reports_test.rb index a5b8825..241654a 100644 --- a/test/system/reports_test.rb +++ b/test/system/reports_test.rb @@ -1,35 +1,37 @@ -require 'application_system_test_case' +# frozen_string_literal: true + +require "application_system_test_case" class ReportsTest < ApplicationSystemTestCase setup do @report = reports(:one) end - test 'visiting the index' do + test "visiting the index" do visit reports_url - assert_selector 'h1', text: 'Prüfberichte' + assert_selector "h1", text: "Prüfberichte" end - test 'should create report' do + test "should create report" do visit reports_url - click_on 'Prüfbericht hinzufügen' + click_on "Prüfbericht hinzufügen" - fill_in_rich_text_area 'Projektbeschreibung', with: @report.comment_html - fill_in 'Bezeichnung', with: @report.name - click_on 'Prüfbericht erstellen' + fill_in_rich_text_area "Projektbeschreibung", with: @report.comment_html + fill_in "Bezeichnung", with: @report.name + click_on "Prüfbericht erstellen" end - test 'should update Report' do + test "should update Report" do visit report_url(@report) - click_on 'Prüfbericht bearbeiten', match: :first + click_on "Prüfbericht bearbeiten", match: :first - fill_in_rich_text_area 'Projektbeschreibung', with: @report.comment_html - fill_in 'Bezeichnung', with: @report.name - click_on 'Prüfbericht aktualisieren' + fill_in_rich_text_area "Projektbeschreibung", with: @report.comment_html + fill_in "Bezeichnung", with: @report.name + click_on "Prüfbericht aktualisieren" end - test 'should destroy Report' do + test "should destroy Report" do visit report_url(@report) - click_on 'Prüfbericht löschen', match: :first + click_on "Prüfbericht löschen", match: :first end end diff --git a/test/system/success_criteria_test.rb b/test/system/success_criteria_test.rb index e4e77cb..deef90a 100644 --- a/test/system/success_criteria_test.rb +++ b/test/system/success_criteria_test.rb @@ -1,44 +1,46 @@ -require 'application_system_test_case' +# frozen_string_literal: true + +require "application_system_test_case" class SuccessCriteriaTest < ApplicationSystemTestCase setup do @success_criterion = success_criteria(:one) end - test 'visiting the index' do + test "visiting the index" do visit success_criteria_url - assert_selector 'h1', text: 'Erfolgskriterien' + assert_selector "h1", text: "Erfolgskriterien" end - test 'should create Erfolgskriterium' do + test "should create Erfolgskriterium" do visit success_criteria_url - click_on 'Erfolgskriterium hinzufügen' + click_on "Erfolgskriterium hinzufügen" - fill_in_rich_text_area 'Testkommentar', with: @success_criterion.comment_html - fill_in_rich_text_area 'Richtlinie', with: @success_criterion.description_html + fill_in_rich_text_area "Testkommentar", with: @success_criterion.comment_html + fill_in_rich_text_area "Richtlinie", with: @success_criterion.description_html # fill_in 'Element', with: @success_criterion.element_id # fill_in 'Level', with: @success_criterion.level # fill_in 'Result', with: @success_criterion.result # fill_in 'Title', with: @success_criterion.title - click_on 'Erfolgskriterium erstellen' + click_on "Erfolgskriterium erstellen" end - test 'should update Erfolgskriterium' do + test "should update Erfolgskriterium" do visit success_criterion_url(@success_criterion) - click_on 'Erfolgskriterium bearbeiten', match: :first + click_on "Erfolgskriterium bearbeiten", match: :first - fill_in_rich_text_area 'Testkommentar', with: @success_criterion.comment_html - fill_in_rich_text_area 'Richtlinie', with: @success_criterion.description_html - find('label', text: 'Bestanden', visible: true).click - fill_in 'Titel', with: 'new' - click_on 'Erfolgskriterium aktualisieren' + fill_in_rich_text_area "Testkommentar", with: @success_criterion.comment_html + fill_in_rich_text_area "Richtlinie", with: @success_criterion.description_html + find("label", text: "Bestanden", visible: true).click + fill_in "Titel", with: "new" + click_on "Erfolgskriterium aktualisieren" # assert_text 'Erfolgskriterium was successfully updated' # click_on 'Back' end - test 'should destroy Erfolgskriterium' do + test "should destroy Erfolgskriterium" do visit success_criterion_url(@success_criterion) - click_on 'Erfolgskriterium löschen', match: :first + click_on "Erfolgskriterium löschen", match: :first end end diff --git a/test/test_helper.rb b/test/test_helper.rb index 3e6dca6..a84c711 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -1,9 +1,9 @@ # frozen_string_literal: true -ENV['RAILS_ENV'] ||= 'test' -require_relative '../config/environment' -require 'rails/test_help' -require 'action_text/system_test_helper' +ENV["RAILS_ENV"] ||= "test" +require_relative "../config/environment" +require "rails/test_help" +require "action_text/system_test_helper" module ActiveSupport class TestCase
<%= Check.human_attribute_name(:id) %><%= Check.human_attribute_name(:level) %><%= Check.human_attribute_name(:number) %> <%= Check.human_attribute_name(:name) %><%= Check.human_attribute_name(:success_criterion_html) %><%= Check.human_attribute_name(:standards) %><%= t("checks.target_disabilities") %><%= t("checks.applicability") %><%= Check.human_attribute_name(:external_number) %><%= Check.human_attribute_name(:conformity_level) %>
<%= check.id %><%= check.level %><%= link_to(check.name, url_for(check)) %><%= link_to(truncate(strip_tags(check.success_criterion_html.to_s)), url_for(check)) %><%= check.number %><%= check.t_name %><%= check.standards.map(&:t_name).join(", ") %><%= check.display_target_disabilities %><%= check.t_name %><%= check.t_name %><%= link_to(check.t_name, url_for(check)) %>
<%= link_to(link_category.name, url_for(link_category)) %><%= link_to(link_category.description, url_for(link_category)) %><%= link_to(truncate(link_category.description.to_plain_text), url_for(link_category)) %>