diff --git a/.dockerignore b/.dockerignore
index 36170e5..f53753f 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -41,3 +41,5 @@
/.forgejo/
/core*
+
+/.devenv
diff --git a/.gitignore b/.gitignore
index 1298bd2..f77ab27 100644
--- a/.gitignore
+++ b/.gitignore
@@ -74,3 +74,5 @@ public/504.html
public/505.html
public/507.html
public/510.html
+
+/.devenv
diff --git a/.ruby-version b/.ruby-version
index f13c6f4..0f9e134 100644
--- a/.ruby-version
+++ b/.ruby-version
@@ -1 +1 @@
-ruby-3.3.5
+ruby-3.4
diff --git a/Dockerfile b/Dockerfile
index d7dcac6..4573018 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,19 +1,19 @@
+ARG RUBY_VERSION=3.4
+
ARG NAME=app
ARG UID=1000
ARG GID=1000
-ARG APP_PORT=3000
-ARG INSTALL_DIR=/${NAME}
-ARG RUBY_VERSION=3.2.5
-FROM ruby:${RUBY_VERSION} AS development
+ARG INSTALL_DIR=/home/${NAME}/src
+
+FROM ruby:${RUBY_VERSION} as development
+
+LABEL maintainer='david@hohl.cloud'
ARG NAME
ARG UID
ARG GID
-ARG APP_PORT
ARG INSTALL_DIR
-LABEL maintainer='david@hohl.cloud'
-
WORKDIR ${INSTALL_DIR}
ENV GEM_HOME=${INSTALL_DIR}/.bundle
@@ -39,6 +39,7 @@ RUN \
--disabled-login \
--shell /bin/bash \
${NAME} && \
+ chown -R ${NAME}:${NAME} /home/${NAME} && \
apt-get update && \
apt-get install -yqq --no-install-recommends \
gnupg2 \
@@ -47,9 +48,8 @@ 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 libjemalloc2 && \
+ sqlite3 nodejs npm sassc yarn libvips libjemalloc2 && \
apt-get clean && \
- npm install tabby-agent && \
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* && \
truncate -s 0 /var/log/*log && \
gem update --system && \
@@ -57,135 +57,91 @@ RUN \
ENV LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.2
-USER ${NAME}
-
-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
-
-FROM ruby:${RUBY_VERSION}-alpine AS builder
-
-ARG NAME
-ARG UID
-ARG GID
-ARG APP_PORT
-ARG INSTALL_DIR
-
-WORKDIR ${INSTALL_DIR}
-
-ENV GEM_HOME=${INSTALL_DIR}/.bundle
-
-ENV \
- LANG=C.UTF-8 \
- INSTALL_DIR=${INSTALL_DIR} \
- RAILS_ENV=development \
- TZ=Europe/Zurich \
- PATH=${INSTALL_DIR}/bin:$GEM_HOME/bin:$GEM_HOME/gems/bin:$PATH \
- EDITOR=vim
-
-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}
-
-ENV LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.2
+COPY bin/dev_entrypoint /usr/local/bin/dev_entrypoint
USER ${NAME}
+ENTRYPOINT ["/usr/local/bin/dev_entrypoint"]
+
+CMD ["/bin/sh", "-c", "dev"]
+
+FROM development AS build
+
USER root
-COPY Gemfile Gemfile.lock package.json yarn.lock ./
+# Wir wollen die bundles nicht im app directory
+ENV GEM_HOME=/usr/local/bundle \
+ BUNDLE_WITHOUT="development test" \
+ RAILS_ENV=production \
+ SECRET_KEY_BASE_DUMMY=1
+
+ENV PATH=${INSTALL_DIR}/bin:$GEM_HOME/bin:$GEM_HOME/gems/bin:$PATH
-RUN bundle config without test development && bundle install && yarn install
+COPY ./Gemfile ./Gemfile.lock ./
-FROM builder AS assets
+RUN bundle config set app_config ${GEM_HOME} && \
+ bundle config && \
+ bundle install && \
+ rm -rf ~/.bundle/ "${BUNDLE_PATH}"/ruby/*/cache "${BUNDLE_PATH}"/ruby/*/bundler/gems/*/.git && \
+ bundle exec bootsnap precompile --gemfile
+
+RUN bundle config
COPY . .
-COPY --from=builder ${INSTALL_DIR}/.bundle ${INSTALL_DIR}/.bundle
-COPY --from=builder ${INSTALL_DIR}/node_modules ${INSTALL_DIR}/node_modules
+RUN bundle exec bootsnap precompile app/ lib/ && \
+ rails assets:precompile && \
+ rm -rf log/* tmp/* && \
+ chown -R ${NAME}:${NAME} log tmp
-RUN RAILS_ENV=production SECRET_KEY_BASE_DUMMY=1 rails assets:precompile
-FROM ruby:${RUBY_VERSION}-alpine AS production
+FROM ruby:${RUBY_VERSION}-slim AS release
-ARG INSTALL_DIR
-ARG NAME
+ARG UID
+ARG GID
+ARG NAME=app
+ARG INSTALL_DIR
+ARG BUILD_DIR=${INSTALL_DIR}
+ARG INSTALL_DIR=/app
+
+ENV GEM_HOME=/usr/local/bundle \
+ BUNDLE_WITHOUT="development test" \
+ BUNDLE_SYSTEM=1 \
+ RAILS_ENV=production \
+ LANG=C.UTF-8 \
+ INSTALL_DIR=${INSTALL_DIR} \
+ TZ=Europe/Zurich
+
+ENV PATH=${INSTALL_DIR}/bin:$GEM_HOME/bin:$GEM_HOME/gems/bin:$PATH
WORKDIR ${INSTALL_DIR}
-ENV GEM_HOME=${INSTALL_DIR}/.bundle
+RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && \
+ echo $TZ > /etc/timezone && \
+ adduser --disabled-password --disabled-login ${NAME} &&\
+ apt-get update -yqq && \
+ apt-get install -yqq --no-install-recommends \
+ sqlite3 libjemalloc2 && \
+ apt-get clean && \
+ rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* && \
+ gem update --system && \
+ truncate -s 0 /var/log/*log
+
+ENV LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.2
-ENV \
- RAILS_ENV=production \
- PATH=${INSTALL_DIR}/bin:$GEM_HOME/bin:$GEM_HOME/gems/bin:$PATH \
- TZ=Europe/Zurich
+RUN pwd
-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
+COPY --from=build ${GEM_HOME} ${GEM_HOME}
+COPY --from=build ${BUILD_DIR} .
+
+RUN ls -la && chown -R ${NAME}:${NAME} ./tmp ./log ./storage
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
+ENTRYPOINT ["bin/docker-entrypoint"]
USER ${NAME}
-ENTRYPOINT [ "bin/entrypoint" ]
+CMD ["./bin/rails", "server", "-b", "0"]
+
-CMD [ "rails", "server", "--binding", "0.0.0.0", "--no-daemon", "--port" , "3000" ]
diff --git a/Gemfile b/Gemfile
index 4819425..67d1a34 100644
--- a/Gemfile
+++ b/Gemfile
@@ -2,8 +2,6 @@
source "https://rubygems.org"
-ruby "3.2.5"
-
# Bundle edge Rails instead: gem "rails", github: "rails/rails", branch: "main"
gem "rails", "~> 8.0"
@@ -50,6 +48,7 @@ gem "bootsnap", require: false
gem "bootstrap_form"
gem "caxlsx"
gem "caxlsx_rails"
+gem "deepl-rb", require: "deepl"
gem "image_processing", "~> 1.2"
gem "openxml-docx"
gem "pagy", "~> 9.0"
@@ -58,6 +57,7 @@ gem "prawn-markup"
gem "prawn-rails"
gem "sablon"
gem "slim"
+gem "solid_queue"
group :development, :test do
# See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem
diff --git a/Gemfile.lock b/Gemfile.lock
index be0da77..bf0065f 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -1,29 +1,29 @@
GEM
remote: https://rubygems.org/
specs:
- actioncable (8.0.0)
- actionpack (= 8.0.0)
- activesupport (= 8.0.0)
+ actioncable (8.0.2)
+ actionpack (= 8.0.2)
+ activesupport (= 8.0.2)
nio4r (~> 2.0)
websocket-driver (>= 0.6.1)
zeitwerk (~> 2.6)
- actionmailbox (8.0.0)
- actionpack (= 8.0.0)
- activejob (= 8.0.0)
- activerecord (= 8.0.0)
- activestorage (= 8.0.0)
- activesupport (= 8.0.0)
+ actionmailbox (8.0.2)
+ actionpack (= 8.0.2)
+ activejob (= 8.0.2)
+ activerecord (= 8.0.2)
+ activestorage (= 8.0.2)
+ activesupport (= 8.0.2)
mail (>= 2.8.0)
- actionmailer (8.0.0)
- actionpack (= 8.0.0)
- actionview (= 8.0.0)
- activejob (= 8.0.0)
- activesupport (= 8.0.0)
+ actionmailer (8.0.2)
+ actionpack (= 8.0.2)
+ actionview (= 8.0.2)
+ activejob (= 8.0.2)
+ activesupport (= 8.0.2)
mail (>= 2.8.0)
rails-dom-testing (~> 2.2)
- actionpack (8.0.0)
- actionview (= 8.0.0)
- activesupport (= 8.0.0)
+ actionpack (8.0.2)
+ actionview (= 8.0.2)
+ activesupport (= 8.0.2)
nokogiri (>= 1.8.5)
rack (>= 2.2.4)
rack-session (>= 1.0.1)
@@ -31,35 +31,35 @@ GEM
rails-dom-testing (~> 2.2)
rails-html-sanitizer (~> 1.6)
useragent (~> 0.16)
- actiontext (8.0.0)
- actionpack (= 8.0.0)
- activerecord (= 8.0.0)
- activestorage (= 8.0.0)
- activesupport (= 8.0.0)
+ actiontext (8.0.2)
+ actionpack (= 8.0.2)
+ activerecord (= 8.0.2)
+ activestorage (= 8.0.2)
+ activesupport (= 8.0.2)
globalid (>= 0.6.0)
nokogiri (>= 1.8.5)
- actionview (8.0.0)
- activesupport (= 8.0.0)
+ actionview (8.0.2)
+ activesupport (= 8.0.2)
builder (~> 3.1)
erubi (~> 1.11)
rails-dom-testing (~> 2.2)
rails-html-sanitizer (~> 1.6)
- activejob (8.0.0)
- activesupport (= 8.0.0)
+ activejob (8.0.2)
+ activesupport (= 8.0.2)
globalid (>= 0.3.6)
- activemodel (8.0.0)
- activesupport (= 8.0.0)
- activerecord (8.0.0)
- activemodel (= 8.0.0)
- activesupport (= 8.0.0)
+ activemodel (8.0.2)
+ activesupport (= 8.0.2)
+ activerecord (8.0.2)
+ activemodel (= 8.0.2)
+ activesupport (= 8.0.2)
timeout (>= 0.4.0)
- activestorage (8.0.0)
- actionpack (= 8.0.0)
- activejob (= 8.0.0)
- activerecord (= 8.0.0)
- activesupport (= 8.0.0)
+ activestorage (8.0.2)
+ actionpack (= 8.0.2)
+ activejob (= 8.0.2)
+ activerecord (= 8.0.2)
+ activesupport (= 8.0.2)
marcel (~> 1.0)
- activesupport (8.0.0)
+ activesupport (8.0.2)
base64
benchmark (>= 0.3)
bigdecimal
@@ -74,18 +74,18 @@ GEM
uri (>= 0.13.1)
addressable (2.8.7)
public_suffix (>= 2.0.2, < 7.0)
- ast (2.4.2)
+ ast (2.4.3)
base64 (0.2.0)
bcrypt (3.1.20)
benchmark (0.4.0)
- bigdecimal (3.1.8)
+ bigdecimal (3.1.9)
bindex (0.8.1)
- bootsnap (1.18.3)
+ bootsnap (1.18.6)
msgpack (~> 1.2)
bootstrap_form (5.4.0)
actionpack (>= 6.1)
activemodel (>= 6.1)
- brakeman (6.1.2)
+ brakeman (7.0.2)
racc
builder (3.3.0)
capybara (3.40.0)
@@ -97,7 +97,7 @@ GEM
rack-test (>= 0.6.3)
regexp_parser (>= 1.5, < 3.0)
xpath (~> 3.2)
- caxlsx (4.1.0)
+ caxlsx (4.2.0)
htmlentities (~> 4.3, >= 4.3.4)
marcel (~> 1.0)
nokogiri (~> 1.10, >= 1.10.4)
@@ -105,47 +105,57 @@ GEM
caxlsx_rails (0.6.4)
actionpack (>= 3.1)
caxlsx (>= 3.0)
- concurrent-ruby (1.3.3)
- connection_pool (2.4.1)
+ concurrent-ruby (1.3.5)
+ connection_pool (2.5.3)
crass (1.0.6)
- cssbundling-rails (1.4.0)
+ cssbundling-rails (1.4.3)
railties (>= 6.0.0)
- date (3.4.0)
- debug (1.9.2)
+ date (3.4.1)
+ debug (1.10.0)
irb (~> 1.10)
reline (>= 0.3.8)
+ deepl-rb (3.2.0)
drb (2.2.1)
- erubi (1.13.0)
- ffi (1.17.0-aarch64-linux-gnu)
- ffi (1.17.0-arm-linux-gnu)
- ffi (1.17.0-arm64-darwin)
- ffi (1.17.0-x86-linux-gnu)
- ffi (1.17.0-x86_64-darwin)
- ffi (1.17.0-x86_64-linux-gnu)
+ erubi (1.13.1)
+ et-orbi (1.2.11)
+ tzinfo
+ ffi (1.17.2-aarch64-linux-gnu)
+ ffi (1.17.2-aarch64-linux-musl)
+ ffi (1.17.2-arm-linux-gnu)
+ ffi (1.17.2-arm-linux-musl)
+ ffi (1.17.2-arm64-darwin)
+ ffi (1.17.2-x86_64-darwin)
+ ffi (1.17.2-x86_64-linux-gnu)
+ ffi (1.17.2-x86_64-linux-musl)
+ fugit (1.11.1)
+ et-orbi (~> 1, >= 1.2.11)
+ raabro (~> 1.4)
globalid (1.2.1)
activesupport (>= 6.1)
hpricot (0.8.6)
html2slim (0.2.0)
hpricot
htmlentities (4.3.4)
- i18n (1.14.5)
+ i18n (1.14.7)
concurrent-ruby (~> 1.0)
- image_processing (1.12.2)
- mini_magick (>= 4.9.5, < 5)
+ image_processing (1.14.0)
+ mini_magick (>= 4.9.5, < 6)
ruby-vips (>= 2.0.17, < 3)
- io-console (0.7.2)
- irb (1.14.0)
+ io-console (0.8.0)
+ irb (1.15.2)
+ pp (>= 0.6.0)
rdoc (>= 4.0.0)
reline (>= 0.4.2)
- jbuilder (2.12.0)
+ jbuilder (2.13.0)
actionview (>= 5.0.0)
activesupport (>= 5.0.0)
- jsbundling-rails (1.3.0)
+ jsbundling-rails (1.3.1)
railties (>= 6.0.0)
- json (2.7.2)
- language_server-protocol (3.17.0.3)
- logger (1.6.1)
- loofah (2.22.0)
+ json (2.12.0)
+ language_server-protocol (3.17.0.5)
+ lint_roller (1.1.0)
+ logger (1.7.0)
+ loofah (2.24.1)
crass (~> 1.0.2)
nokogiri (>= 1.12.0)
mail (2.8.1)
@@ -155,31 +165,37 @@ GEM
net-smtp
marcel (1.0.4)
matrix (0.4.2)
- mini_magick (4.13.2)
+ mini_magick (5.2.0)
+ benchmark
+ logger
mini_mime (1.1.5)
- minitest (5.24.1)
- msgpack (1.7.2)
- net-imap (0.5.0)
+ minitest (5.25.5)
+ msgpack (1.8.0)
+ net-imap (0.5.8)
date
net-protocol
net-pop (0.1.2)
net-protocol
net-protocol (0.2.2)
timeout
- net-smtp (0.5.0)
+ net-smtp (0.5.1)
net-protocol
- nio4r (2.7.3)
- nokogiri (1.16.6-aarch64-linux)
+ nio4r (2.7.4)
+ nokogiri (1.18.8-aarch64-linux-gnu)
racc (~> 1.4)
- nokogiri (1.16.6-arm-linux)
+ nokogiri (1.18.8-aarch64-linux-musl)
racc (~> 1.4)
- nokogiri (1.16.6-arm64-darwin)
+ nokogiri (1.18.8-arm-linux-gnu)
racc (~> 1.4)
- nokogiri (1.16.6-x86-linux)
+ nokogiri (1.18.8-arm-linux-musl)
racc (~> 1.4)
- nokogiri (1.16.6-x86_64-darwin)
+ nokogiri (1.18.8-arm64-darwin)
racc (~> 1.4)
- nokogiri (1.16.6-x86_64-linux)
+ nokogiri (1.18.8-x86_64-darwin)
+ racc (~> 1.4)
+ nokogiri (1.18.8-x86_64-linux-gnu)
+ racc (~> 1.4)
+ nokogiri (1.18.8-x86_64-linux-musl)
racc (~> 1.4)
openxml-docx (0.11.5)
nokogiri
@@ -189,76 +205,83 @@ GEM
openxml-drawingml (0.3.1)
nokogiri
openxml-package (~> 0.3.2)
- openxml-package (0.3.4)
+ openxml-package (0.3.5)
nokogiri
ox
- rubyzip
- ox (2.14.18)
- pagy (9.0.2)
+ rubyzip (~> 2.3)
+ ox (2.14.22)
+ bigdecimal (>= 3.0)
+ pagy (9.3.4)
pandoc-ruby (2.1.10)
- parallel (1.25.1)
- parser (3.3.4.0)
+ parallel (1.27.0)
+ parser (3.3.8.0)
ast (~> 2.4.1)
racc
pdf-core (0.10.0)
+ pp (0.6.2)
+ prettyprint
prawn (2.5.0)
matrix (~> 0.4)
pdf-core (~> 0.10.0)
ttfunk (~> 1.8)
- prawn-markup (1.0.0)
+ prawn-markup (1.1.0)
nokogiri
prawn
prawn-table
- prawn-rails (1.4.2)
+ prawn-rails (1.6.0)
actionview (>= 3.1.0)
+ activesupport (>= 3.1.0)
prawn
prawn-table
prawn-table (0.2.2)
prawn (>= 1.3.0, < 3.0.0)
- prism (1.2.0)
+ prettyprint (0.2.0)
+ prism (1.4.0)
propshaft (1.1.0)
actionpack (>= 7.0.0)
activesupport (>= 7.0.0)
rack
railties (>= 7.0.0)
- psych (5.1.2)
+ psych (5.2.6)
+ date
stringio
- public_suffix (6.0.0)
- puma (6.4.2)
+ public_suffix (6.0.2)
+ puma (6.6.0)
nio4r (~> 2.0)
- racc (1.8.0)
- rack (3.1.7)
- rack-session (2.0.0)
+ raabro (1.4.0)
+ racc (1.8.1)
+ rack (3.1.14)
+ rack-session (2.1.1)
+ base64 (>= 0.1.0)
rack (>= 3.0.0)
- rack-test (2.1.0)
+ rack-test (2.2.0)
rack (>= 1.3)
- rackup (2.1.0)
+ rackup (2.2.1)
rack (>= 3)
- webrick (~> 1.8)
- rails (8.0.0)
- actioncable (= 8.0.0)
- actionmailbox (= 8.0.0)
- actionmailer (= 8.0.0)
- actionpack (= 8.0.0)
- actiontext (= 8.0.0)
- actionview (= 8.0.0)
- activejob (= 8.0.0)
- activemodel (= 8.0.0)
- activerecord (= 8.0.0)
- activestorage (= 8.0.0)
- activesupport (= 8.0.0)
+ rails (8.0.2)
+ actioncable (= 8.0.2)
+ actionmailbox (= 8.0.2)
+ actionmailer (= 8.0.2)
+ actionpack (= 8.0.2)
+ actiontext (= 8.0.2)
+ actionview (= 8.0.2)
+ activejob (= 8.0.2)
+ activemodel (= 8.0.2)
+ activerecord (= 8.0.2)
+ activestorage (= 8.0.2)
+ activesupport (= 8.0.2)
bundler (>= 1.15.0)
- railties (= 8.0.0)
+ railties (= 8.0.2)
rails-dom-testing (2.2.0)
activesupport (>= 5.0.0)
minitest
nokogiri (>= 1.6)
- rails-html-sanitizer (1.6.0)
+ rails-html-sanitizer (1.6.2)
loofah (~> 2.21)
- nokogiri (~> 1.14)
- railties (8.0.0)
- actionpack (= 8.0.0)
- activesupport (= 8.0.0)
+ nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0)
+ railties (8.0.2)
+ actionpack (= 8.0.2)
+ activesupport (= 8.0.2)
irb (~> 1.13)
rackup (>= 1.0.0)
rake (>= 12.2)
@@ -266,62 +289,62 @@ GEM
zeitwerk (~> 2.6)
rainbow (3.1.1)
rake (13.2.1)
- rbs (3.6.1)
+ rbs (3.9.4)
logger
- rdoc (6.7.0)
+ rdoc (6.13.1)
psych (>= 4.0.0)
- regexp_parser (2.9.2)
- reline (0.5.9)
+ regexp_parser (2.10.0)
+ reline (0.6.1)
io-console (~> 0.5)
- rexml (3.3.2)
- strscan
- rubocop (1.65.0)
+ rexml (3.4.1)
+ rubocop (1.75.6)
json (~> 2.3)
- language_server-protocol (>= 3.17.0)
+ language_server-protocol (~> 3.17.0.2)
+ lint_roller (~> 1.1.0)
parallel (~> 1.10)
parser (>= 3.3.0.2)
rainbow (>= 2.2.2, < 4.0)
- regexp_parser (>= 2.4, < 3.0)
- rexml (>= 3.2.5, < 4.0)
- rubocop-ast (>= 1.31.1, < 2.0)
+ regexp_parser (>= 2.9.3, < 3.0)
+ rubocop-ast (>= 1.44.0, < 2.0)
ruby-progressbar (~> 1.7)
- unicode-display_width (>= 2.4.0, < 3.0)
- rubocop-ast (1.31.3)
- 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)
+ unicode-display_width (>= 2.4.0, < 4.0)
+ rubocop-ast (1.44.1)
+ parser (>= 3.3.7.2)
+ prism (~> 1.4)
+ rubocop-capybara (2.22.1)
+ lint_roller (~> 1.1)
+ rubocop (~> 1.72, >= 1.72.1)
+ rubocop-performance (1.25.0)
+ lint_roller (~> 1.1)
+ rubocop (>= 1.75.0, < 2.0)
+ rubocop-ast (>= 1.38.0, < 2.0)
+ rubocop-rails (2.31.0)
activesupport (>= 4.2.0)
+ lint_roller (~> 1.1)
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.20.1)
+ rubocop (>= 1.75.0, < 2.0)
+ rubocop-ast (>= 1.38.0, < 2.0)
+ rubocop-rails-omakase (1.1.0)
+ rubocop (>= 1.72)
+ rubocop-performance (>= 1.24)
+ rubocop-rails (>= 2.30)
+ ruby-lsp (0.23.20)
language_server-protocol (~> 3.17.0)
prism (>= 1.2, < 2.0)
rbs (>= 3, < 4)
sorbet-runtime (>= 0.5.10782)
- ruby-lsp-rails (0.3.21)
- ruby-lsp (>= 0.20.0, < 0.21.0)
+ ruby-lsp-rails (0.4.3)
+ ruby-lsp (>= 0.23.18, < 0.24.0)
ruby-progressbar (1.13.0)
- ruby-vips (2.2.1)
+ ruby-vips (2.2.3)
ffi (~> 1.12)
- rubyzip (2.3.2)
+ logger
+ rubyzip (2.4.1)
sablon (0.4.1)
nokogiri (>= 1.8.5)
rubyzip (>= 1.3.0)
- securerandom (0.3.1)
- selenium-webdriver (4.23.0)
+ securerandom (0.4.1)
+ selenium-webdriver (4.32.0)
base64 (~> 0.2)
logger (~> 1.4)
rexml (~> 3.2, >= 3.2.5)
@@ -330,53 +353,64 @@ GEM
slim (5.2.1)
temple (~> 0.10.0)
tilt (>= 2.1.0)
- sorbet-runtime (0.5.11625)
- sqlite3 (2.2.0-aarch64-linux-gnu)
- sqlite3 (2.2.0-arm-linux-gnu)
- sqlite3 (2.2.0-arm64-darwin)
- sqlite3 (2.2.0-x86-linux-gnu)
- sqlite3 (2.2.0-x86_64-darwin)
- sqlite3 (2.2.0-x86_64-linux-gnu)
- stimulus-rails (1.3.3)
+ solid_queue (1.1.5)
+ activejob (>= 7.1)
+ activerecord (>= 7.1)
+ concurrent-ruby (>= 1.3.1)
+ fugit (~> 1.11.0)
+ railties (>= 7.1)
+ thor (~> 1.3.1)
+ sorbet-runtime (0.5.12109)
+ sqlite3 (2.6.0-aarch64-linux-gnu)
+ sqlite3 (2.6.0-aarch64-linux-musl)
+ sqlite3 (2.6.0-arm-linux-gnu)
+ sqlite3 (2.6.0-arm-linux-musl)
+ sqlite3 (2.6.0-arm64-darwin)
+ sqlite3 (2.6.0-x86_64-darwin)
+ sqlite3 (2.6.0-x86_64-linux-gnu)
+ sqlite3 (2.6.0-x86_64-linux-musl)
+ stimulus-rails (1.3.4)
railties (>= 6.0.0)
- stringio (3.1.1)
- strscan (3.1.0)
+ stringio (3.1.7)
temple (0.10.3)
- thor (1.3.1)
- tilt (2.4.0)
- timeout (0.4.1)
+ thor (1.3.2)
+ tilt (2.6.0)
+ timeout (0.4.3)
ttfunk (1.8.0)
bigdecimal (~> 3.1)
- turbo-rails (2.0.5)
- actionpack (>= 6.0.0)
- activejob (>= 6.0.0)
- railties (>= 6.0.0)
+ turbo-rails (2.0.13)
+ actionpack (>= 7.1.0)
+ railties (>= 7.1.0)
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
- unicode-display_width (2.5.0)
- uri (1.0.1)
- useragent (0.16.10)
+ unicode-display_width (3.1.4)
+ unicode-emoji (~> 4.0, >= 4.0.4)
+ unicode-emoji (4.0.4)
+ uri (1.0.3)
+ useragent (0.16.11)
web-console (4.2.1)
actionview (>= 6.0.0)
activemodel (>= 6.0.0)
bindex (>= 0.4.0)
railties (>= 6.0.0)
- webrick (1.8.1)
websocket (1.2.11)
- websocket-driver (0.7.6)
+ websocket-driver (0.7.7)
+ base64
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.5)
xpath (3.2.0)
nokogiri (~> 1.8)
- zeitwerk (2.6.16)
+ zeitwerk (2.7.2)
PLATFORMS
- aarch64-linux
- arm-linux
+ aarch64-linux-gnu
+ aarch64-linux-musl
+ arm-linux-gnu
+ arm-linux-musl
arm64-darwin
- x86-linux
x86_64-darwin
- x86_64-linux
+ x86_64-linux-gnu
+ x86_64-linux-musl
DEPENDENCIES
bcrypt (~> 3.1.7)
@@ -388,6 +422,7 @@ DEPENDENCIES
caxlsx_rails
cssbundling-rails
debug
+ deepl-rb
html2slim
image_processing (~> 1.2)
jbuilder
@@ -409,14 +444,12 @@ DEPENDENCIES
sablon
selenium-webdriver
slim
+ solid_queue
sqlite3 (>= 2.1)
stimulus-rails
turbo-rails
tzinfo-data
web-console
-RUBY VERSION
- ruby 3.2.5p208
-
BUNDLED WITH
- 2.5.15
+ 2.6.2
diff --git a/Procfile.dev b/Procfile.dev
index 66fe22e..8cec4c8 100644
--- a/Procfile.dev
+++ b/Procfile.dev
@@ -1,3 +1,3 @@
-web: env RUBY_DEBUG_OPEN=true bin/rails server -b 0
-js: yarn build --watch
+web: RUBY_DEBUG_OPEN=true bin/rails server -b 0
+js: yarn build --watch=forever
css: yarn watch:css
diff --git a/README.md b/README.md
index 4f83e3b..ec40b05 100644
--- a/README.md
+++ b/README.md
@@ -2,3 +2,7 @@
`rails new -n a11yist -d sqlite3 --skip-action-mailbox --css bootstrap --js esbuild .`
+
+## Installation
+
+To [install](readme)
diff --git a/app/assets/images/logo-apfelschule.png b/app/assets/images/logo-apfelschule.png
index 475c455..d603a48 100644
Binary files a/app/assets/images/logo-apfelschule.png and b/app/assets/images/logo-apfelschule.png differ
diff --git a/app/assets/images/logo-apfelschule_xs.png b/app/assets/images/logo-apfelschule_xs.png
new file mode 100644
index 0000000..d9d46ff
Binary files /dev/null and b/app/assets/images/logo-apfelschule_xs.png differ
diff --git a/app/assets/stylesheets/application.bootstrap.scss b/app/assets/stylesheets/application.bootstrap.scss
index 19d4485..1846b2d 100644
--- a/app/assets/stylesheets/application.bootstrap.scss
+++ b/app/assets/stylesheets/application.bootstrap.scss
@@ -28,13 +28,8 @@ $enable-rounded: false;
@import 'bootstrap/scss/bootstrap';
-@font-face {
- font-display: block;
- font-family: "bootstrap-icons";
- src: url("./bootstrap-icons.woff2") format("woff2"),
- url("./bootstrap-icons.woff") format("woff");
-}
-
+$lg-path-images: "";
+$bootstrap-icons-font-dir: "";
@import 'bootstrap-icons/font/bootstrap-icons';
@@ -52,6 +47,10 @@ $enable-rounded: false;
@import "trix/dist/trix";
+$lg-path-fonts: "";
+
+@import "lightgallery/scss/lightgallery";
+
/*
* Provides a drop-in pointer for the default Trix stylesheet that will format the toolbar and
* the trix-editor content (whether displayed or under editing). Feel free to incorporate this
@@ -164,4 +163,5 @@ trix-toolbar .trix-dialog--link {
overflow-y: auto;
} */
-@import "./layout";
\ No newline at end of file
+@import "./layout";
+@import "./dropdown";
\ No newline at end of file
diff --git a/app/assets/stylesheets/dropdown.scss b/app/assets/stylesheets/dropdown.scss
new file mode 100644
index 0000000..b8bb038
--- /dev/null
+++ b/app/assets/stylesheets/dropdown.scss
@@ -0,0 +1,67 @@
+.details-dropdown {
+ display: inline-block;
+ position: relative;
+}
+
+/* Hide The disclosure widget: */
+.details-dropdown summary {
+ list-style: none;
+ cursor: pointer;
+}
+.details-dropdown[open] summary {
+ list-style: none;
+ cursor: pointer;
+ i {
+
+ color: var(--bs-body-color)
+ }
+ /* border-left: solid 1px $secondary; */
+ /* border-top: solid 1px $secondary; */
+ /* border-right: solid 1px $secondary; */
+}
+.details-dropdown[open] {
+ background-color: $secondary;
+}
+
+/* Detache details content */
+.details-dropdown .details-dropdown-content {
+ border: solid 1px $secondary;
+ position: absolute;
+ min-inline-size: max-content;
+ z-index: 2000;
+
+ /* In case the details-dropdown should open to the left: */
+ right: 0;
+}
+
+/* Closing the details-dropdown on clicking anywhere else */
+.details-dropdown[open] summary::before {
+ position: fixed;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ content: "";
+ cursor: default;
+}
+
+/* Visual styles for your details-dropdown: */
+.details-dropdown .details-dropdown-trigger {
+ /* your look and feel here */
+}
+
+.details-dropdown .details-dropdown-content {
+ /* your look and feel here */
+}
+
+form.no-padding {
+ button {
+ padding: 0;
+ }
+}
+
+li.list-group-item-danger:hover {
+ button {
+ color: var(--bs-body-color) !important;
+ }
+}
diff --git a/app/assets/stylesheets/layout.scss b/app/assets/stylesheets/layout.scss
index 8700b9d..dc4e19e 100644
--- a/app/assets/stylesheets/layout.scss
+++ b/app/assets/stylesheets/layout.scss
@@ -20,37 +20,6 @@ $tertiary-dark-active-open: $gray-600;
}
}
-// // Fix trix dark mode
-// .trix-button-row {
-// .trix-button-group {
-// border: var(--bs-border-width) solid var(--bs-border-color);
-
-// .trix-button {
-// border: 0;
-// }
-// }
-// }
-
-// [data-bs-theme=dark] {
-// .trix-button-row {
-// .trix-button-group {
-// .trix-button {
-// background-color: transparent;
-// filter: invert(100%);
-// }
-// }
-// }
-// }
-// // end fix trix dark mode
-
-// .trix-content pre {
-// background-color: var(--bs-secondary-bg);
-// color: var(--bs-secondary-color);
-// border: var(--bs-border-width) solid var(--bs-border-color);
-// border-radius: var(--bs-border-radius);
-// padding: var(--bs-padding);
-// }
-
.hover-row:hover {
background-color: var(--bs-tertiary-bg);
}
@@ -91,7 +60,10 @@ $tertiary-dark-active-open: $gray-600;
.page_nav nav ul {
padding-left: 0;
list-style-type: none;
- line-height: 2rem;
+
+ li {
+ margin-bottom: 0.5rem;
+ }
a {
color: var(--bs-text);
@@ -223,7 +195,15 @@ details.tree[open]>summary::before {
padding-bottom: 0;
}
+details.success_criterion:last-child {
+ border-bottom: solid 1px $tertiary;
+}
+
details.success_criterion {
+ border-left: solid 1px $tertiary;
+ border-right: solid 0px $tertiary;
+ border-top: solid 0px $tertiary;
+
summary:hover {
background-color: $tertiary-hover;
@@ -239,6 +219,7 @@ details.success_criterion {
>.content {
padding-left: 1rem;
padding-right: 1rem;
+ padding-bottom: 1rem;
}
}
@@ -253,26 +234,36 @@ details.success_criterion {
details.success_criterion[open] {
- border: solid 1px $tertiary;
+ /* border: solid 1px $tertiary; */
- summary {
+ >summary {
background-color: $tertiary;
}
- summary:hover {
+ >summary:hover {
background-color: $tertiary-active-hover;
}
}
@include color-mode(dark) {
- details.success_criterion[open] {
- border: solid 1px $tertiary-dark;
+ details.success_criterion {
+ border-left: solid 1px $tertiary-dark;
+ border-right: solid 1px $tertiary-dark;
+ border-top: solid 1px $tertiary-dark;
+ }
- summary {
+ details.success_criterion:last-child {
+ border-bottom: solid 1px $tertiary-dark;
+ }
+
+ details.success_criterion[open] {
+ /* border: solid 1px $tertiary-dark; */
+
+ >summary {
background-color: $tertiary-dark;
}
- summary:hover {
+ >summary:hover {
background-color: $tertiary-dark-active-open;
}
}
@@ -326,4 +317,65 @@ details[open] {
.sortable-ghost {
border: solid 3px $primary !important;
+}
+
+$dialog-animation-time: 0.5s;
+$dialog-animation-start-state: scaleX(1);
+$dialog-animation-end-state: scaleX(1);
+/* dialog::backdrop { */
+/* background-color: white; */
+/* opacity: 0.75; */
+/* } */
+
+/* Open state of the dialog */
+dialog[open] {
+ opacity: 1;
+ transform: $dialog-animation-end-state;
+}
+
+/* Closed state of the dialog */
+dialog {
+ opacity: 0;
+ transform: $dialog-animation-start-state;
+ transition:
+ opacity $dialog-animation-time ease-out,
+ transform $dialog-animation-time ease-out,
+ overlay $dialog-animation-time ease-out allow-discrete,
+ display $dialog-animation-time ease-out allow-discrete;
+ /* Equivalent to
+ transition: all $dialog-animation-time allow-discrete; */
+}
+
+/* Before-open state */
+/* Needs to be after the previous dialog[open] rule to take effect,
+ as the specificity is the same */
+@starting-style {
+ dialog[open] {
+ opacity: 0;
+ transform: $dialog-animation-start-state;
+ }
+}
+
+/* Transition the :backdrop when the dialog modal is promoted to the top layer */
+dialog::backdrop {
+ background-color: rgb(0 0 0 / 75%);
+ transition:
+ display $dialog-animation-time allow-discrete,
+ overlay $dialog-animation-time allow-discrete,
+ background-color $dialog-animation-time;
+ /* Equivalent to
+ transition: all $dialog-animation-time allow-discrete; */
+}
+
+dialog[open]::backdrop {
+ background-color: rgb(0 0 0 / 75%);
+}
+
+/* This starting-style rule cannot be nested inside the above selector
+because the nesting selector cannot represent pseudo-elements. */
+
+@starting-style {
+ dialog[open]::backdrop {
+ background-color: rgb(0 0 0 / 0%);
+ }
}
\ No newline at end of file
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 3804ad6..41d97ec 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -22,9 +22,9 @@ class ApplicationController < ActionController::Base
path: :root
},
{
- label: Report.model_name.human(count: 2),
- icon: :'journal-text',
- path: :reports },
+ label: Project.model_name.human(count: 2),
+ icon: :'folder',
+ path: :projects },
{
label: I18n.t("backoffice"),
icon: :gear,
@@ -32,7 +32,8 @@ class ApplicationController < ActionController::Base
active: %w[backoffice checklists checks links link_categories].include?(controller_name) },
{
label: "Konto",
- path: profile_path
+ path: profile_path,
+ icon: "person-circle"
}
]
else
@@ -50,4 +51,8 @@ class ApplicationController < ActionController::Base
def initialize_sidebar_items
[]
end
+
+ def render_modal(action: action_name)
+ render action, layout: "modal" if turbo_frame_request_id == "modal"
+ end
end
diff --git a/app/controllers/checks_controller.rb b/app/controllers/checks_controller.rb
index 551e7c2..f1c1e3e 100644
--- a/app/controllers/checks_controller.rb
+++ b/app/controllers/checks_controller.rb
@@ -81,7 +81,7 @@ class ChecksController < ApplicationController
# Only allow a list of trusted parameters through.
def check_params
- params.require(:check).permit(:principle_id,
+ params.require(:check).permit(:guideline_id,
:number,
:name_de,
:name_en,
@@ -95,7 +95,9 @@ class ChecksController < ApplicationController
:applicable_to_analogue,
:applicable_to_document,
:applicable_to_non_web,
- :external_number,
+ :external_number_1,
+ :external_number_2,
+ :external_number_3,
:external_url,
:conformity_level,
:conformity_notice_de,
diff --git a/app/controllers/concerns/authentication.rb b/app/controllers/concerns/authentication.rb
index 771b21d..8cae6ea 100644
--- a/app/controllers/concerns/authentication.rb
+++ b/app/controllers/concerns/authentication.rb
@@ -21,7 +21,6 @@ module Authentication
resume_session || request_authentication
end
-
def resume_session
Current.session ||= find_session_by_cookie
end
@@ -30,7 +29,6 @@ module Authentication
Session.find_by(id: cookies.signed[:session_id])
end
-
def request_authentication
session[:return_to_after_authenticating] = request.url
redirect_to new_session_path
@@ -40,7 +38,6 @@ module Authentication
session.delete(:return_to_after_authenticating) || root_url
end
-
def start_new_session_for(user)
user.sessions.create!(user_agent: request.user_agent, ip_address: request.remote_ip).tap do |session|
Current.session = session
diff --git a/app/controllers/concerns/backoffice_menu.rb b/app/controllers/concerns/backoffice_menu.rb
index e2f72fb..9ab5278 100644
--- a/app/controllers/concerns/backoffice_menu.rb
+++ b/app/controllers/concerns/backoffice_menu.rb
@@ -5,6 +5,7 @@ module BackofficeMenu
[
{ label: "Einstellungen", icon: :sliders, path: :backoffice },
{ label: Checklist.model_name.human(count: 2), icon: :'list-check', path: :checklists },
+ { label: Guideline.model_name.human(count: 2), icon: :'rulers', path: :guidelines },
{ 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 } ]
diff --git a/app/controllers/elements_controller.rb b/app/controllers/elements_controller.rb
index 152c904..fd94e84 100644
--- a/app/controllers/elements_controller.rb
+++ b/app/controllers/elements_controller.rb
@@ -19,7 +19,9 @@ class ElementsController < ApplicationController
end
# GET /elements/1/edit
- def edit; end
+ def edit
+ render_modal
+ end
# POST /elements
def create
@@ -87,6 +89,6 @@ class ElementsController < ApplicationController
# Only allow a list of trusted parameters through.
def element_params
- params.require(:element).permit(:page_id, :title, :description, :position)
+ params.require(:element).permit(:page_id, :title, :description, :position, :screenshot)
end
end
diff --git a/app/controllers/guidelines_controller.rb b/app/controllers/guidelines_controller.rb
new file mode 100644
index 0000000..e69449d
--- /dev/null
+++ b/app/controllers/guidelines_controller.rb
@@ -0,0 +1,58 @@
+class GuidelinesController < BackofficeController
+ before_action :set_guideline, only: %i[ show edit update destroy ]
+
+ # GET /guidelines
+ def index
+ @guidelines = Guideline.all
+ end
+
+ # GET /guidelines/1
+ def show
+ end
+
+ # GET /guidelines/new
+ def new
+ @guideline = Guideline.new
+ end
+
+ # GET /guidelines/1/edit
+ def edit
+ end
+
+ # POST /guidelines
+ def create
+ @guideline = Guideline.new(guideline_params)
+
+ if @guideline.save
+ redirect_to @guideline, notice: "Guideline was successfully created."
+ else
+ render :new, status: :unprocessable_entity
+ end
+ end
+
+ # PATCH/PUT /guidelines/1
+ def update
+ if @guideline.update(guideline_params)
+ redirect_to @guideline, notice: "Guideline was successfully updated.", status: :see_other
+ else
+ render :edit, status: :unprocessable_entity
+ end
+ end
+
+ # DELETE /guidelines/1
+ def destroy
+ @guideline.destroy!
+ redirect_to guidelines_url, notice: "Guideline was successfully destroyed.", status: :see_other
+ end
+
+ private
+ # Use callbacks to share common setup or constraints between actions.
+ def set_guideline
+ @guideline = Guideline.find(params[:id])
+ end
+
+ # Only allow a list of trusted parameters through.
+ def guideline_params
+ params.require(:guideline).permit(:principle_id, :number, :name_de, :name_en, :description_de, :description_en)
+ end
+end
diff --git a/app/controllers/home_controller.rb b/app/controllers/home_controller.rb
index 9d3293e..46103e2 100644
--- a/app/controllers/home_controller.rb
+++ b/app/controllers/home_controller.rb
@@ -20,11 +20,6 @@ class HomeController < ApplicationController
path: profile_path,
active: action_name == "profile"
},
- # {
- # label: "Passwort ändern",
- # path: new_password_path,
- # icon: :lock
- # },
{
label: "Logout",
icon: :"box-arrow-right",
diff --git a/app/controllers/pages_controller.rb b/app/controllers/pages_controller.rb
index 13f2fb8..c73d631 100644
--- a/app/controllers/pages_controller.rb
+++ b/app/controllers/pages_controller.rb
@@ -19,6 +19,7 @@ class PagesController < ApplicationController
# GET /pages/1/edit
def edit
+ render_modal
end
# POST /pages
diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb
new file mode 100644
index 0000000..a61963c
--- /dev/null
+++ b/app/controllers/projects_controller.rb
@@ -0,0 +1,62 @@
+class ProjectsController < ApplicationController
+ before_action :set_project, only: %i[ show edit update destroy ]
+
+ # GET /projects
+ def index
+ @projects = Project.all
+ end
+
+ # GET /projects/1
+ def show
+ end
+
+ # GET /projects/new
+ def new
+ @project = Project.new
+ end
+
+ # GET /projects/1/edit
+ def edit
+ end
+
+ # POST /projects
+ def create
+ @project = if params[:copy_from_id]
+ Project.find(params[:copy_from_id]).dup
+ else
+ Project.new(project_params)
+ end
+
+ if @project.save
+ redirect_to @project, notice: "Project was successfully created."
+ else
+ render :new, status: :unprocessable_entity
+ end
+ end
+
+ # PATCH/PUT /projects/1
+ def update
+ if @project.update(project_params)
+ redirect_to @project, notice: "Project was successfully updated.", status: :see_other
+ else
+ render :edit, status: :unprocessable_entity
+ end
+ end
+
+ # DELETE /projects/1
+ def destroy
+ @project.destroy!
+ redirect_to projects_url, notice: "Project was successfully destroyed.", status: :see_other
+ end
+
+ private
+ # Use callbacks to share common setup or constraints between actions.
+ def set_project
+ @project = Project.find(params[:id])
+ end
+
+ # Only allow a list of trusted parameters through.
+ def project_params
+ params.require(:project).permit(:name, :details)
+ end
+end
diff --git a/app/controllers/reports_controller.rb b/app/controllers/reports_controller.rb
index d1733d5..3ec1e8b 100644
--- a/app/controllers/reports_controller.rb
+++ b/app/controllers/reports_controller.rb
@@ -1,11 +1,12 @@
# frozen_string_literal: true
class ReportsController < ApplicationController
+ before_action :set_project, only: %i[index new create]
before_action :set_report, only: %i[show edit update destroy work]
# GET /reports
def index
- @reports = Report.all
+ @reports = @project.reports
end
# GET /reports/1
@@ -85,7 +86,7 @@ class ReportsController < ApplicationController
# GET /reports/new
def new
- @report = Report.new
+ @report = Report.new(project_id: @project.id)
end
# GET /reports/1/edit
@@ -93,10 +94,45 @@ class ReportsController < ApplicationController
# POST /reports
def create
- @report = Report.new(report_params)
+ success = if params[:copy_from_id]
+ original = Report.find(params[:copy_from_id])
+ @report = original.dup
+ @report.pages = original.pages.map do |page|
+ page.dup.tap do |p|
+ p.elements = page.elements.map do |element|
+ element.dup.tap do |e|
+ e.success_criteria = element.success_criteria.map do |sc|
+ csc = sc.dup
+ SuccessCriterion.rich_text_association_names
+ .map { _1.to_s.sub(/^rich_text_/, "") }
+ .each do |a|
+ csc.send("#{a}=", sc.send(a).dup)
+ end
+ csc
+ end
+ e.screenshot = element.screenshot&.dup
+ Element.rich_text_association_names
+ .map { _1.to_s.sub(/^rich_text_/, "") }
+ .each do |a|
+ e.send("#{a}=", element.send(a).dup)
+ end
+ end
+ end
+ Page.rich_text_association_names
+ .map { _1.to_s.sub(/^rich_text_/, "") }
+ .each do |a|
+ p.send("#{a}=", page.send(a).dup)
+ end
+ end
+ end
+ @report.save
+ else
+ @report = Report.new(report_params.merge(project_id: @project.id))
+ @report.save
+ end
- if @report.save
- redirect_to @report, notice: "Report was successfully created."
+ if success
+ redirect_to @report.reload, notice: "Report was successfully created."
else
render :new, status: :unprocessable_entity
end
@@ -114,7 +150,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 project_url(@report.project), notice: "Report was successfully destroyed.", status: :see_other
end
def work
@@ -130,7 +166,7 @@ class ReportsController < ApplicationController
# Only allow a list of trusted parameters through.
def report_params
- params.require(:report).permit(:name, :comment, :url)
+ params.require(:report).permit(:name, :comment, :url, :project_id)
end
def filename(report, extension: "html")
@@ -140,4 +176,8 @@ class ReportsController < ApplicationController
def page_param
params[:page_id]
end
+
+ def set_project
+ @project = Project.find(params[:project_id])
+ end
end
diff --git a/app/controllers/success_criteria_controller.rb b/app/controllers/success_criteria_controller.rb
index 4ae7840..a180f99 100644
--- a/app/controllers/success_criteria_controller.rb
+++ b/app/controllers/success_criteria_controller.rb
@@ -2,7 +2,7 @@
class SuccessCriteriaController < ApplicationController
before_action :set_element, only: %i[new create index new_from_checklist create_from_checklist]
- before_action :set_success_criterion, only: %i[show edit update destroy]
+ before_action :set_success_criterion, only: %i[show edit update destroy edit_comment]
# GET /success_criteria
def index
@@ -18,7 +18,9 @@ class SuccessCriteriaController < ApplicationController
end
# GET /success_criteria/1/edit
- def edit; end
+ def edit
+ render_modal()
+ end
# POST /success_criteria
def create
@@ -106,6 +108,10 @@ class SuccessCriteriaController < ApplicationController
end
end
+ def edit_comment
+ render_modal()
+ end
+
private
# Use callbacks to share common setup or constraints between actions.
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index de268bb..437f6fc 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -20,7 +20,7 @@ module ApplicationHelper
end
def safe_display(value, &block)
- return unless value
+ return if value.blank?
yield(value)
end
@@ -28,4 +28,41 @@ module ApplicationHelper
def current_page_displayed(page)
@current_page&.id == page.id ? "open" : nil
end
+
+ def turbo_stream_toast(content, alert)
+ turbo_stream.append("toasts", partial: "layouts/toast", locals: { content:, alert: })
+ end
+
+
+ def dropdown_menu(items, klass: "")
+ tag.details(class: "details-dropdown #{klass}", data: { controller: "dropdown-menu" }) do
+ tag.summary do
+ tag.div(class: "details-dropdown-trigger") do
+ tag.div(tag.i(class: "bi bi-three-dots"), class: "btn btn-outline-body")
+ end
+ end +
+ tag.div(class: "details-dropdown-content bg-secondary") do
+ tag.div(class: "list-group") do
+ safe_join(items.map do |item|
+ c = "list-group-item list-group-item-action #{ item[:color] ? " list-group-item-#{item[:color]}" : "list-group-item-secondary"}"
+ text = item[:icon] ? tag.i(class: "bi bi-#{item[:icon]} me-2") + " #{item[:text]}".html_safe : item[:text]
+ case item[:method]
+ when nil, :get
+ link_to(text, item[:href], class: "#{c}", data: { turbo_frame: item[:turbo_frame], action: item[:action] })
+ else
+ button_to(text,
+ item[:href],
+ method: item[:method],
+ class: "#{c}",
+ data: { turbo_confirm: item[:confirm] })
+ end
+ end)
+ end
+ end
+ end
+ end
+
+ def modal?
+ turbo_frame_request_id == "modal"
+ end
end
diff --git a/app/helpers/elements_helper.rb b/app/helpers/elements_helper.rb
index d7f10ce..1488e59 100644
--- a/app/helpers/elements_helper.rb
+++ b/app/helpers/elements_helper.rb
@@ -1,4 +1,19 @@
# frozen_string_literal: true
module ElementsHelper
+ def element_menu(element)
+ dropdown_menu([
+ { text: "Bearbeiten",
+ icon: "pencil",
+ href: edit_element_path(element),
+ turbo_frame: "modal",
+ color: "body" },
+ { text: "Löschen",
+ icon: "trash",
+ href: element_path(element),
+ color: :danger,
+ method: :delete,
+ confirm: "Bist du sicher?" } ],
+ klass: "ms-auto")
+ end
end
diff --git a/app/helpers/pages_helper.rb b/app/helpers/pages_helper.rb
index 2c057fd..6aa2874 100644
--- a/app/helpers/pages_helper.rb
+++ b/app/helpers/pages_helper.rb
@@ -1,2 +1,27 @@
module PagesHelper
+ def page_menu(page)
+ dropdown_menu([
+ {
+ text: "Alle zu [s]",
+ href: "#",
+ action: "click->details-list#closeAll"
+ },
+ {
+ text: "Alle auf [a]",
+ href: "#",
+ action: "click->details-list#openAll"
+ },
+ { text: "Bearbeiten",
+ icon: "pencil",
+ href: edit_page_path(page),
+ turbo_frame: "modal",
+ color: "body" },
+ { text: "Löschen",
+ icon: "trash",
+ href: page_path(page),
+ color: :danger,
+ method: :delete,
+ confirm: "Bist du sicher?" } ],
+ klass: "ms-auto")
+ end
end
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
new file mode 100644
index 0000000..db5c5ce
--- /dev/null
+++ b/app/helpers/projects_helper.rb
@@ -0,0 +1,2 @@
+module ProjectsHelper
+end
diff --git a/app/helpers/success_criteria_helper.rb b/app/helpers/success_criteria_helper.rb
index f15ebcc..4b786fe 100644
--- a/app/helpers/success_criteria_helper.rb
+++ b/app/helpers/success_criteria_helper.rb
@@ -25,8 +25,23 @@ module SuccessCriteriaHelper
end
end
+ def success_criterion_menu(success_criterion, show_mode = true)
+ dropdown_menu([
+ { text: "Bearbeiten",
+ icon: "pencil",
+ href: edit_success_criterion_path(success_criterion),
+ turbo_frame: "modal",
+ color: "body" },
+ { text: "Löschen",
+ icon: "trash",
+ href: success_criterion_path(success_criterion),
+ color: :danger,
+ method: :delete,
+ confirm: "Bist du sicher?" } ],
+ klass: "mt-3 ms-auto")
+ end
- def success_criterion_edit_button(success_criterion, edit_mode)
+ def success_criterion_edit_button(success_criterion, edit_mode)
path = if success_criterion.persisted?
if edit_mode
success_criterion
@@ -37,9 +52,9 @@ module SuccessCriteriaHelper
else
success_criterion.element
end
- link_to tag.i(class: "bi bi-pencil"),
+ link_to tag.i(class: "bi bi-pencil") + " Bearbeiten".html_safe,
path,
- class: "btn btn-#{edit_mode ? 'link text-warning' : 'link text-body'}"
+ class: "text-decoration-none xbtn xbtn-#{edit_mode ? 'link text-warning' : 'link text-body'}"
end
def success_criterion_badge(content, extra_classes: "")
diff --git a/app/javascript/application.js b/app/javascript/application.js
index 4b59f32..ae46376 100644
--- a/app/javascript/application.js
+++ b/app/javascript/application.js
@@ -1,7 +1,6 @@
// Entry point for the build script in your package.json
import "@hotwired/turbo-rails"
import "./controllers"
-import * as bootstrap from "bootstrap"
import "trix"
import "@rails/actiontext"
diff --git a/app/javascript/controllers/details_list_controller.js b/app/javascript/controllers/details_list_controller.js
index d521c4c..29a265a 100644
--- a/app/javascript/controllers/details_list_controller.js
+++ b/app/javascript/controllers/details_list_controller.js
@@ -10,7 +10,7 @@ export default class extends Controller {
e.preventDefault();
const id = this.element.dataset["targetId"]
const el = document.getElementById(id)
- el.querySelectorAll("details").forEach(el => {
+ el.querySelectorAll("details.success_criterion").forEach(el => {
el.setAttribute("open", "")
})
}
@@ -19,7 +19,7 @@ export default class extends Controller {
e.preventDefault();
const id = this.element.dataset["targetId"]
const el = document.getElementById(id)
- el.querySelectorAll("details").forEach(el => {
+ el.querySelectorAll("details.success_criterion").forEach(el => {
el.removeAttribute("open")
})
}
diff --git a/app/javascript/controllers/dialog_controller.js b/app/javascript/controllers/dialog_controller.js
new file mode 100644
index 0000000..4dabac7
--- /dev/null
+++ b/app/javascript/controllers/dialog_controller.js
@@ -0,0 +1,53 @@
+// app/javascript/controllers/dialog_controller.js
+import { Controller } from "@hotwired/stimulus"
+
+// Connects to data-controller="dialog"
+export default class extends Controller {
+ connect() {
+ this.open()
+ console.log("connect dialog", this.element)
+ this.element.addEventListener("turbo:submit-end", e => {
+ this.submitEnd(e)
+ })
+ this.element.addEventListener("click", e => this.clickOutside(e))
+ }
+
+ disconnect() {
+ }
+
+ // hide modal on successful form submission
+ // data-action="turbo:submit-end->turbo-modal#submitEnd"
+ submitEnd(e) {
+ if (e.detail.success) {
+ this.close()
+ }
+ }
+
+ open() {
+ console.log("open dialog")
+ this.element.showModal()
+ document.body.classList.add('overflow-hidden')
+ this.element.addEventListener("close", this.enableBodyScroll.bind(this))
+ }
+
+ close() {
+ this.element.removeEventListener("close", this.enableBodyScroll.bind(this))
+ this.element.close()
+ // clean up modal content
+ const frame = document.getElementById('modal')
+ frame.removeAttribute("src")
+ frame.innerHTML = ""
+ }
+
+ enableBodyScroll() {
+ document.body.classList.remove('overflow-hidden')
+ }
+
+ clickOutside(event) {
+ console.log("clickOutside", event.target, this)
+ if (event.target === this.element) {
+ this.close()
+ }
+ }
+}
+
diff --git a/app/javascript/controllers/dropdown_menu_controller.js b/app/javascript/controllers/dropdown_menu_controller.js
new file mode 100644
index 0000000..adbbec8
--- /dev/null
+++ b/app/javascript/controllers/dropdown_menu_controller.js
@@ -0,0 +1,16 @@
+import { Controller } from "@hotwired/stimulus"
+
+// Connects to data-controller="dropdown-menu"
+export default class extends Controller {
+ connect() {
+ const x = this.element
+ this.element.addEventListener("turbo:click", e => {
+ console.log("turbo visit dropdown", e, this.element)
+ this.element.removeAttribute("open");
+ })
+ this.element.addEventListener("turbo:submit-start", e => {
+ console.log("turbo submit dropdown", e, this.element)
+ this.element.removeAttribute("open");
+ })
+ }
+}
diff --git a/app/javascript/controllers/index.js b/app/javascript/controllers/index.js
index 6803226..c4c4879 100644
--- a/app/javascript/controllers/index.js
+++ b/app/javascript/controllers/index.js
@@ -4,6 +4,9 @@
import { application } from "./application"
+import Lightbox from '@stimulus-components/lightbox'
+application.register('lightbox', Lightbox)
+
import AutosubmitController from "./autosubmit_controller"
application.register("autosubmit", AutosubmitController)
@@ -19,9 +22,15 @@ application.register("collapse-chevron-toggler", CollapseChevronTogglerControlle
import DetailsListController from "./details_list_controller"
application.register("details-list", DetailsListController)
+import DialogController from "./dialog_controller"
+application.register("dialog", DialogController)
+
import DragController from "./drag_controller"
application.register("drag", DragController)
+import DropdownMenuController from "./dropdown_menu_controller"
+application.register("dropdown-menu", DropdownMenuController)
+
import HelloController from "./hello_controller"
application.register("hello", HelloController)
@@ -43,5 +52,8 @@ application.register("sortable", SortableController)
import ThemeSwitcherController from "./theme_switcher_controller"
application.register("theme-switcher", ThemeSwitcherController)
+import ToastController from "./toast_controller"
+application.register("toast", ToastController)
+
import UnsavedChangesController from "./unsaved_changes_controller"
application.register("unsaved-changes", UnsavedChangesController)
diff --git a/app/javascript/controllers/toast_controller.js b/app/javascript/controllers/toast_controller.js
new file mode 100644
index 0000000..e8b23e8
--- /dev/null
+++ b/app/javascript/controllers/toast_controller.js
@@ -0,0 +1,14 @@
+import { Controller } from "@hotwired/stimulus"
+import * as bootstrap from "bootstrap"
+
+// Connects to data-controller="toast"
+export default class extends Controller {
+ connect() {
+ const shownKey = `toastsShown[${this.element.getAttribute("data-ts")}]`
+ if(!window.sessionStorage.getItem(shownKey)) {
+ window.sessionStorage.setItem(shownKey, Date.now());
+ const toastBootstrap = bootstrap.Toast.getOrCreateInstance(this.element)
+ toastBootstrap.show()
+ }
+ }
+}
diff --git a/app/models/check.rb b/app/models/check.rb
index a201aa8..a60d5e2 100644
--- a/app/models/check.rb
+++ b/app/models/check.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
class Check < ApplicationRecord
- belongs_to :principle
+ belongs_to :guideline
has_and_belongs_to_many :links
has_and_belongs_to_many :standards
@@ -51,9 +51,9 @@ class Check < ApplicationRecord
:standard_text,
:powerpoint_text
- validates :number, uniqueness: true, presence: true
+ validates :number, uniqueness: { scope: :guideline_id }, presence: true
- before_validation { self.number = self.class.maximum(:id).to_i + 1 unless self.number.present? }
+ # before_validation { self.number = self.class.maximum(:id).to_i + 1 unless self.number.present? }
scope(:search, lambda { |terms|
# TODO: Search only fields for current locale.
@@ -129,4 +129,20 @@ class Check < ApplicationRecord
def external_number
[ external_number_1, external_number_2, external_number_3 ].compact_blank.join(".")
end
+
+ def external_number
+ [
+ guideline.principle.id,
+ guideline.number,
+ number
+ ].compact.join(".")
+ end
+
+ def full_number
+ external_number
+ end
+
+ def to_s
+ display_label
+ end
end
diff --git a/app/models/element.rb b/app/models/element.rb
index b46e492..84af4be 100644
--- a/app/models/element.rb
+++ b/app/models/element.rb
@@ -11,6 +11,12 @@ class Element < ApplicationRecord
before_validation :set_position
before_update :update_positions, if: :position_changed?
+ has_one_attached :screenshot do |attachable|
+ attachable.variant :thumbnail, resize_to_limit: [ 200, 200 ]
+ end
+
+ scope :failed, -> { where(SuccessCriterion.where(result: SuccessCriterion.results[:failed]).arel.exists) }
+
# Calculate actual conformity level:
# - if a success_criterion has result :failed -> the confirmity_level
# of that success_criterion is not reached.
diff --git a/app/models/guideline.rb b/app/models/guideline.rb
new file mode 100644
index 0000000..baeac74
--- /dev/null
+++ b/app/models/guideline.rb
@@ -0,0 +1,18 @@
+class Guideline < ApplicationRecord
+ belongs_to :principle
+
+ has_many :checks
+
+ has_rich_text :description_de
+ has_rich_text :description_en
+
+ translates_attributes :name, :description
+
+ def to_s
+ "#{full_number} #{t_name}"
+ end
+
+ def full_number
+ [ principle.id, number ].join(".")
+ end
+end
diff --git a/app/models/pdf_documents/base.rb b/app/models/pdf_documents/base.rb
index c21d790..8484f62 100644
--- a/app/models/pdf_documents/base.rb
+++ b/app/models/pdf_documents/base.rb
@@ -2,7 +2,7 @@
module PdfDocuments
class Base
- attr_reader :params
+ attr_reader :params, :font
def initialize(prawn_document, **params)
@prawn_document = prawn_document
@@ -13,7 +13,8 @@ module PdfDocuments
# exta_bold: 'vendor/assets/fonts/Lexend-ExtraBold.ttf',
# italic: 'vendor/assets/fonts/Lexend-Regular.ttf'
# })
- @prawn_document.font "Helvetica", size: 12
+ @font = "Helvetica"
+ @prawn_document.font @font, size: 12
@params = OpenStruct.new(params)
end
@@ -40,8 +41,12 @@ module PdfDocuments
@prawn_document.markup "
#{text}
"
end
- def text(text)
- @prawn_document.text text, markup_options[:text]
+ def heading4(text)
+ @prawn_document.markup "#{text}
"
+ end
+
+ def text(text, **args)
+ @prawn_document.text text, markup_options[:text].merge(args)
end
def rich_text(text)
@@ -55,28 +60,28 @@ module PdfDocuments
def markup_options
{
text: { size: 12, margin_bottom: 5 },
- heading1: { style: :bold, size: 26, margin_bottom: 10, margin_top: 0 },
- heading2: { style: :bold, size: 17, margin_bottom: 10, margin_top: 5 },
- heading3: { style: :bold, size: 13, margin_bottom: 10, margin_top: 5 },
- heading4: { style: :bold, size: 12, margin_bottom: 10, margin_top: 5 },
- heading5: { style: :bold, size: 12, margin_bottom: 10, margin_top: 5 },
- heading6: { style: :thin, size: 12, margin_bottom: 10, margin_top: 5 }
+ heading1: { style: :bold, size: 26, margin_bottom: 5, margin_top: 0 },
+ heading2: { style: :bold, size: 17, margin_bottom: 5, margin_top: 5 },
+ heading3: { style: :bold, size: 13, margin_bottom: 5, margin_top: 5 },
+ heading4: { style: :bold, size: 12, margin_bottom: 5, margin_top: 5 },
+ heading5: { style: :bold, size: 12, margin_bottom: 5, margin_top: 5 },
+ heading6: { style: :thin, size: 12, margin_bottom: 5, margin_top: 5 }
}
end
- def logo
- @prawn_document.image "app/assets/images/logo-apfelschule.png", width: 150
- @prawn_document.move_down 30
+ def logo(width: 24, xs: true)
+ @prawn_document.image "app/assets/images/logo-apfelschule#{ xs ? "_xs" : "" }.png", width:
end
def prepare_rich_text(rich_text)
- { h1: "h4" }.each do |tag, replacement|
+ { h1: "h5" }.each do |tag, replacement|
rich_text = rich_text.to_s.gsub("<#{tag}", "<#{replacement}")
rich_text = rich_text.to_s.gsub("#{tag}>", "#{replacement}>")
end
- rich_text
+ rich_text.sub(/(
)+$/, "")
end
+ # @prawn_document.draw_text("Dokument erstellt am #{Time.current.strftime('%d %B %Y')} um #{Time.current.strftime('%H:%M:%S')}", at: [ 0, -15 ])
def font(...)
@prawn_document.font(...)
@@ -89,5 +94,58 @@ module PdfDocuments
def move_down(...)
@prawn_document.move_down(...)
end
+
+ def safe_display(value, &block)
+ return if value.blank?
+
+ begin
+ yield(value)
+ rescue StandardError
+ nil
+ end
+ end
+
+ def bold(text)
+ @prawn_document.font(@font, style: :bold) do
+ @prawn_document.text text
+ end
+ end
+
+ def image(attachable, **args)
+ begin
+ @prawn_document.image(ActiveStorage::Blob.service.path_for(attachable.key), **args) && raise("david")
+ rescue StandardError
+ false
+ end
+ end
+
+ def without_page_break(&block)
+ return yield
+ return @prawn_document.bounding_box([ 0, @prawn_document.cursor ], width: 300) do
+ yield
+ # @prawn_document.stroke_bounds if Rails.env.development?
+ # print_coordinates
+ end
+ @prawn_document.span(520) do
+ yield
+ # @prawn_document.stroke_bounds
+ end
+ end
+
+ def print_coordinates
+ @prawn_document.text("top: #{@prawn_document.bounds.top}")
+ @prawn_document.text("bottom: #{@prawn_document.bounds.bottom}")
+ @prawn_document.text("left: #{@prawn_document.bounds.left}")
+ @prawn_document.text("right: #{@prawn_document.bounds.right}")
+ @prawn_document.move_down(10)
+ @prawn_document.text("absolute top: #{Float(@prawn_document.bounds.absolute_top).round(2)}")
+ @prawn_document.text("absolute bottom: #{Float(@prawn_document.bounds.absolute_bottom).round(2)}")
+ @prawn_document.text("absolute left: #{Float(@prawn_document.bounds.absolute_left).round(2)}")
+ @prawn_document.text("absolute right: #{Float(@prawn_document.bounds.absolute_right).round(2)}")
+ end
+
+ def new_page(required_space: 0)
+ @prawn_document.start_new_page if @prawn_document.cursor <= required_space + 10
+ end
end
end
diff --git a/app/models/pdf_documents/customer_report.rb b/app/models/pdf_documents/customer_report.rb
index 463be57..f64d510 100644
--- a/app/models/pdf_documents/customer_report.rb
+++ b/app/models/pdf_documents/customer_report.rb
@@ -5,26 +5,163 @@ module PdfDocuments
private
def generate
- logo
- @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
-
+ move_down 130
+ logo(width: 250, xs: false)
+ move_down 40
heading1 params.report.name
- rich_text params.report.comment
- 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] } ]
- move_down(5)
- rich_text element.description_html
+ move_down 20
+ @prawn_document.text "#{I18n.l params.report.updated_at.to_date, format: :long}"
+ move_down 40
+ safe_display(params.report.comment) do
+ rich_text _1
+ move_down 30
+ end
- element.success_criteria.each.with_index(1) do |success_criterion, sc_index|
- heading3 "#{element_index}.#{sc_index} #{success_criterion.title}"
- rich_text success_criterion.description_html
- rich_text success_criterion.comment
+ @prawn_document.font_size(8) do
+ @prawn_document.draw_text("Dokument erstellt am #{Time.current.strftime('%d %B %Y')} um #{Time.current.strftime('%H:%M:%S')}", at: [ 0, 0 ])
+ end
+ @prawn_document.start_new_page
+ @pages = {}
+
+ params.report.export[:elements].each.with_index(1) do |(element, success_criteria), element_index|
+ new_page(required_space: 200) if element_index > 1
+ without_page_break do
+ heading2 "#{element_index} #{element.title}"
+ @prawn_document.text("Pfad: #{element.page.path}", inline_format: true)
+ safe_display(element.screenshot) do
+ image(_1.variant(:thumbnail), height: 160)
+ move_down(15)
+ end
+ end
+ rich_text element.description
+ move_down(10)
+
+ success_criteria.each.with_index(1) do |success_criterion, sc_index|
+ @pages[success_criterion] = @prawn_document.page_number
+ success_criterion_row(success_criterion, [ element_index, sc_index ])
+ end
+ end
+
+ @prawn_document.start_new_page
+ heading1("Anhang: Richtlinien")
+ params.report.export[:success_criteria].group_by(&:check).sort_by { |c, _scs| c.external_number }.each do |check, criteria|
+ heading2(check.display_label)
+ @pages[check] = @prawn_document.page_number
+ {
+ external_number: { label: "WCAG Nummer" },
+ external_url: { label: "WCAG Link" },
+ conformity_level: { label: "Konformität" },
+ conformity_notice_de: { label: "Anmerkung Konformität", rich: true },
+ priority: { label: "Priorität" },
+ criterion_de: { label: "Kriterium/Grundlage", rich: true },
+ exemption_details_de: { label: "Ausnahmen", rich: true },
+ criterion_details_de: { label: "Verstehen", rich: true },
+ example_de: { label: "Beispiel", rich: true },
+ annotation_de: { label: "Anmerkung", rich: true }
+ }.each do |attribute, options|
+ v = check.send(attribute)
+ safe_display(v) do
+ text("#{options[:label]}", inline_format: true)
+ if options[:rich]
+ rich_text(_1)
+ else
+ text(_1)
+ end
+ end
+ end
+
+ if check.links.any?
+ move_down 5
+ text("Links", inline_format: true)
+ move_down 5
+ check.links.group_by(&:link_category).each do |cat, links|
+ rich_text(%Q(
+ #{cat.name}
+
+ ))
+ end
+ end
+
+ text("Erfolgskriterien", inline_format: true)
+ text criteria.map(&:number).sort.join(", ")
+ end
+ string = "Seite / "
+ # Green page numbers 1 to 7
+ options = {
+ at: [ @prawn_document.bounds.right - 150, 776 ],
+ width: 150,
+ align: :right,
+ start_count_at: 2,
+ page_filter: ->(x) { x > 1 }
+ }
+ @prawn_document.number_pages string, options
+
+ @prawn_document.repeat(2..) do
+ @prawn_document.text_box "#{params.report.name}", at: [ 50, 777 ], inline_format: true, width: 300
+ @prawn_document.bounding_box([ 0, 766 ], width: 532) do
+ hr
+ end
+ @prawn_document.bounding_box([ 0, 796 ], width: 200, height: 200) do
+ logo
+ end
+ end
+
+ x = params
+ p = @pages
+ @prawn_document.outline.define do
+ x.report.export[:elements].each.with_index(1) do |(element, success_criteria), element_index|
+ section("#{element_index} #{element.title}") do
+ success_criteria.each.with_index(1) do |sc, sc_index|
+ page(title: "#{element_index}.#{sc_index} #{sc.title}", destination: p[sc])
+ end
+ end
+ end
+ section("Anhang: Richtlinien") do
+ x.report.export[:success_criteria].group_by(&:check).sort_by { |c, _scs| c.external_number }.each do |check, _criteria|
+ page(title: check.display_label, destination: p[check])
+ end
end
end
end
+
+ private
+
+ def success_criterion_row(success_criterion, index)
+ heading3 "#{index.join(".")} #{success_criterion.title}"
+ safe_display(success_criterion.test_comment) do
+ without_page_break do
+ heading4 "Kommentar"
+ rich_text success_criterion.test_comment
+ end
+ end
+ safe_display(success_criterion.quick_criterion) do
+ without_page_break do
+ heading4 "Kriterium"
+ rich_text success_criterion.quick_criterion
+ end
+ end
+ safe_display(success_criterion.quick_fail) do
+ without_page_break do
+ heading4 "Fail"
+ rich_text success_criterion.quick_fail
+ end
+ end
+ safe_display(success_criterion.quick_fix) do
+ without_page_break do
+ heading4 "Fix"
+ rich_text success_criterion.quick_fix
+ end
+ end
+ heading4("Protokollnummer")
+ text(success_criterion.number)
+ safe_display(success_criterion.check.external_url) do
+ heading4("WCAG")
+ text("#{success_criterion.check.external_number || _1}", inline_format: true)
+ end
+ move_down(10)
+ end
end
end
diff --git a/app/models/project.rb b/app/models/project.rb
new file mode 100644
index 0000000..2b7f03e
--- /dev/null
+++ b/app/models/project.rb
@@ -0,0 +1,7 @@
+class Project < ApplicationRecord
+ has_many :reports, dependent: :restrict_with_error
+
+ has_rich_text :details
+
+ scope :current, -> { where("updated_at > ?", 1.month.ago) }
+end
diff --git a/app/models/report.rb b/app/models/report.rb
index 7b15df9..df65fc4 100644
--- a/app/models/report.rb
+++ b/app/models/report.rb
@@ -1,9 +1,28 @@
# frozen_string_literal: true
class Report < ApplicationRecord
+ belongs_to :project, touch: true
+
has_many :pages, -> { order(:position) }, dependent: :destroy
has_many :elements, through: :pages, dependent: :destroy
+ has_many :success_criteria, through: :elements, dependent: :destroy
+
has_rich_text :comment
validates :name, presence: true
+
+ def export
+ export_success_criteria = success_criteria.failed
+ export_elements = export_success_criteria.group_by(&:element)
+ export_pages = export_elements.group_by { |k, v| k }
+ {
+ pages: export_pages,
+ elements: export_elements,
+ success_criteria: export_success_criteria
+ }
+ end
+
+ def test
+ 139
+ end
end
diff --git a/app/models/success_criterion.rb b/app/models/success_criterion.rb
index 03c97fa..afe275a 100644
--- a/app/models/success_criterion.rb
+++ b/app/models/success_criterion.rb
@@ -17,6 +17,10 @@ class SuccessCriterion < ApplicationRecord
before_save :set_position
before_update :update_positions, if: :position_changed?
+ validates :result, inclusion: { in: self.results.keys + [ nil ] }
+
+ scope :failed, -> { where(result: :failed) }
+
def level_value
return nil unless level
diff --git a/app/views/backoffice/show.html.erb b/app/views/backoffice/show.html.erb
index c16d394..8bcbd75 100644
--- a/app/views/backoffice/show.html.erb
+++ b/app/views/backoffice/show.html.erb
@@ -7,6 +7,12 @@
<%= link_to Checklist.model_name.human(count: Checklist.count), :checklists %>
+
+
+<%= Guideline.count %>
+<%= link_to Guideline.model_name.human(count: Guideline.count), :guidelines %>
+
+
<%= Check.count %>
@@ -27,4 +33,4 @@
<%= link_to "ZIP Backup herunterladen", admin_backup_url(format: :zip), class: " ", data: { turbo_prefetch: false, frame: "_top", turbo: false } %>
-
\ No newline at end of file
+
diff --git a/app/views/checklist_entries/destroy.turbo_stream.erb b/app/views/checklist_entries/destroy.turbo_stream.erb
index 6e7c01a..4b1f257 100644
--- a/app/views/checklist_entries/destroy.turbo_stream.erb
+++ b/app/views/checklist_entries/destroy.turbo_stream.erb
@@ -1 +1,2 @@
-<%= turbo_stream.remove dom_id(@checklist_entry) %>
\ No newline at end of file
+<%= turbo_stream.remove dom_id(@checklist_entry) %>
+<%= turbo_stream_toast("Check wurde aus Checkliste entfernt", true) %>
diff --git a/app/views/checks/_check.html.slim b/app/views/checks/_check.html.slim
index 62996f0..7f99880 100644
--- a/app/views/checks/_check.html.slim
+++ b/app/views/checks/_check.html.slim
@@ -11,8 +11,8 @@ div id=dom_id(check)
th = Check.human_attribute_name(:number)
td = check.number
tr
- th = Principle.model_name.human
- td = check.principle&.t_name
+ th = Guideline.model_name.human
+ td = check.guideline&.name_en
tr
th = Standard.model_name.human(count: check.standard_ids.size)
td = check.standards.map(&:t_name).sort_by(&:downcase).join(", ")
@@ -80,4 +80,4 @@ div id=dom_id(check)
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/_form.html.slim b/app/views/checks/_form.html.slim
index 53e4bb7..9f5bb2c 100644
--- a/app/views/checks/_form.html.slim
+++ b/app/views/checks/_form.html.slim
@@ -1,9 +1,9 @@
= bootstrap_form_with(model: check, remote: true, data: { controller: "unsaved-changes" }) do |form|
h2 Details
= multilang_form_field(form, :name)
- = form.text_field :number, required: false
.row
- = form.collection_radio_buttons(:principle_id, Principle.all.sort_by(&:t_name), :id, :t_name) { |b| b.label(class: "col-md-2") { b.radio_button + b.text } }
+ = form.collection_radio_buttons(:guideline_id, Guideline.all.sort_by(&:full_number), :id, :to_s) { |b| b.label(class: "col-md-2") { b.radio_button + b.text } }
+ = form.text_field :number, required: false
= form.collection_check_boxes :standard_ids, Standard.all.sort_by{ _1.t_name.downcase }, :id, :t_name, include_blank: true
h2 Einschränkung/Zugänglichkeit
diff --git a/app/views/elements/_element.html.erb b/app/views/elements/_element.html.erb
index 346648f..0c92ffc 100644
--- a/app/views/elements/_element.html.erb
+++ b/app/views/elements/_element.html.erb
@@ -1,6 +1,6 @@
<%= turbo_frame_tag dom_id(element, :frame) do %>
-
+
@@ -9,22 +9,23 @@
<%= element.title %>
- <%= link_to [:edit, element], class: "btn btn-link text-secondary" do %>
-
-
+ <%= element_menu(element) %>
+
+
+
+ <% if element.description %>
+
+ <%= element.description %>
+
<% end %>
- <%= button_to(element_path(element), method: :delete, class: "btn btn-link text-danger", data: { turbo_confirm: "Bist du sicher?"}) do %>
-
+ <% safe_display(element.screenshot) do |s| %>
+
+ <%= link_to(s) do %>
+ <%= image_tag(s.variant(:thumbnail), class: "img-fluid", alt: "Screenshot des getesteten Elements") %>
+ <% end rescue nil %>
+
<% end %>
- <% if element.description %>
-
- <%= element.description %>
-
- <% end %>
-
-
-
<% end %>
diff --git a/app/views/elements/_element.odt.erb b/app/views/elements/_element.odt.erb
index bf1ae9e..fac3639 100644
--- a/app/views/elements/_element.odt.erb
+++ b/app/views/elements/_element.odt.erb
@@ -7,6 +7,9 @@
<%= element.description_html %>
+ <%= image_tag(element.screenshot.preview(:thumbnail)) %>
+ <%= image_tag(element.screenshot) %>
+
<% element.success_criteria.each do |sc| %>
<%= render sc %>
<% end %>
diff --git a/app/views/elements/_form.html.erb b/app/views/elements/_form.html.erb
deleted file mode 100644
index 1795bfc..0000000
--- a/app/views/elements/_form.html.erb
+++ /dev/null
@@ -1,7 +0,0 @@
-<%= bootstrap_form_with(model: element.persisted? ? element : [:page, element], class: "mb-3") do |form| %>
- <%= form.hidden_field :page_id %>
- <%= form.text_field :title %>
- <%= form.rich_text_area :description %>
- <%= form.submit class: "btn btn-primary" %>
- <%= link_to("Abbrechen", element.persisted? ? element : element.report, class: "btn btn-outline-secondary") %>
-<% end %>
diff --git a/app/views/elements/_form.html.slim b/app/views/elements/_form.html.slim
new file mode 100644
index 0000000..b821401
--- /dev/null
+++ b/app/views/elements/_form.html.slim
@@ -0,0 +1,10 @@
+= bootstrap_form_with(model: element.persisted? ? element : [:page, element], class: "mb-3") do |form|
+ = form.hidden_field :page_id
+ = form.text_field :title
+ = form.rich_text_area :description
+ = form.file_field :screenshot
+ - if element.persisted?
+ = safe_display(element.screenshot) { tag.div(link_to(_1.filename.to_s, _1), class: "mb-3") }
+ = form.submit class: "btn btn-primary"
+ - unless modal?
+ = link_to("Abbrechen", element.persisted? ? element : element.report, class: "btn btn-outline-secondary")
diff --git a/app/views/elements/_page_nav_row.html.slim b/app/views/elements/_page_nav_row.html.slim
index 29713b4..7ab20f2 100644
--- a/app/views/elements/_page_nav_row.html.slim
+++ b/app/views/elements/_page_nav_row.html.slim
@@ -1,13 +1,7 @@
-li id=dom_id(element, :page_nav_row) data={ "sortable-url": element_path(element), "form-name": "element", "position-attribute": "position" }
- - if current_page
- =< link_to("##{dom_id(element)}", data: { "turbo": false }) do
- i.bi.bi-boxes.me-2
- span id=dom_id(element, :page_nav_title)
- = "#{element.number} #{element.title}"
- i.bi.bi-grip-vertical.float-end.handle
- - else
- =< link_to(report_path(element.report, page_id: element.page.id, anchor: dom_id(element)), data: { "turbo": false }) do
- i.bi.bi-boxes.me-2
- span id=dom_id(element, :page_nav_title)
- =< "#{element.number} #{element.title}"
- i.bi.bi-grip-vertical.float-end.handle
\ No newline at end of file
+li.d-flex id=dom_id(element, :page_nav_row) data={ "sortable-url": element_path(element), "form-name": "element", "position-attribute": "position" }
+ - url = current_page ? "##{dom_id(element)}" : report_path(element.report, page_id: element.page.id, anchor: dom_id(element))
+ i.bi.bi-boxes.me-2
+ =< link_to(url, data: { "turbo": false }, class: "me-auto") do
+ span id=dom_id(element, :page_nav_title)
+ = "#{element.number} #{element.title}"
+ i.bi.bi-grip-vertical.handle
diff --git a/app/views/elements/create.turbo_stream.slim b/app/views/elements/create.turbo_stream.slim
index 6f8cc39..5c75d05 100644
--- a/app/views/elements/create.turbo_stream.slim
+++ b/app/views/elements/create.turbo_stream.slim
@@ -1,3 +1,6 @@
= turbo_stream.update "new_element_frame", partial: "pages/new_element_button", locals: { page: @element.page }
= turbo_stream.append "element_list", @element
-= turbo_stream.append dom_id(@element.page, :page_nav_elements), partial: "elements/page_nav_row", locals: { element: @element, current_page: true }
\ No newline at end of file
+= turbo_stream.append dom_id(@element.page, :page_nav_elements), partial: "elements/page_nav_row", locals: { element: @element, current_page: true }
+
+
+= turbo_stream_toast("Element hinzugefügt", false)
\ No newline at end of file
diff --git a/app/views/elements/destroy.turbo_stream.slim b/app/views/elements/destroy.turbo_stream.slim
index 6370d37..5305209 100644
--- a/app/views/elements/destroy.turbo_stream.slim
+++ b/app/views/elements/destroy.turbo_stream.slim
@@ -2,4 +2,7 @@
= turbo_stream.remove dom_id(@element, :page_nav_row)
- @element.page.elements.reject { _1 == @element }.each do |e|
= turbo_stream.update dom_id(e, :title), "#{e.page.position}.#{e.position} #{e.title}"
- = turbo_stream.replace dom_id(e, :page_nav_row), partial: "elements/page_nav_row", locals: { element: e, current_page: true }
\ No newline at end of file
+ = turbo_stream.replace dom_id(e, :page_nav_row), partial: "elements/page_nav_row", locals: { element: e, current_page: true }
+
+
+= turbo_stream_toast("Element wurde gelöscht", true)
diff --git a/app/views/elements/edit.html.erb b/app/views/elements/edit.html.erb
index ade1f43..f1e84ae 100644
--- a/app/views/elements/edit.html.erb
+++ b/app/views/elements/edit.html.erb
@@ -1,19 +1,17 @@
<%= t("scaffold.pagetitle_edit", model: Element.model_name.human) %>
-<%= turbo_frame_tag dom_id(@element, :frame) do %>
<%= @element.title %>
- <%= link_to(tag.i(class: "bi bi-pencil"), @element, class: "btn btn-link text-warning") %>
<%= render "form", element: @element %>
+<% unless modal? %>
+
+ <%= link_to t("scaffold.link_show", model: Element.model_name.human), @element %>
+ <%= link_to t("scaffold.link_index", model: Element.model_name.human(count: 2)), page_elements_path(@element.page) %>
+
<% end %>
-
-
- <%= link_to t("scaffold.link_show", model: Element.model_name.human), @element %>
- <%= link_to t("scaffold.link_index", model: Element.model_name.human(count: 2)), page_elements_path(@element.page) %>
-
diff --git a/app/views/elements/update.turbo_stream.slim b/app/views/elements/update.turbo_stream.slim
index e6b478c..a6f1e78 100644
--- a/app/views/elements/update.turbo_stream.slim
+++ b/app/views/elements/update.turbo_stream.slim
@@ -4,4 +4,8 @@
/ - element.success_criteria.each do |sc|
/ = turbo_stream.update dom_id(sc, :title), "#{sc.page.position}.#{sc.element.position}.#{sc.position} #{sc.title}"
- element.success_criteria.each do |sc|
- = turbo_stream.update dom_id(sc, :position), "#{sc.page.position}.#{sc.element.position}.#{sc.position}"
\ No newline at end of file
+ = turbo_stream.update dom_id(sc, :position), "#{sc.page.position}.#{sc.element.position}.#{sc.position}"
+ = turbo_stream.replace dom_id(element, :frame), element
+
+
+= turbo_stream_toast("Element gespeichert", false)
\ No newline at end of file
diff --git a/app/views/exports/show.html.slim b/app/views/exports/show.html.slim
index 2a00726..1fe71d1 100644
--- a/app/views/exports/show.html.slim
+++ b/app/views/exports/show.html.slim
@@ -1,55 +1,99 @@
-h1 id=dom_id(@report) = @report.name
+h1.title id=dom_id(@report) = @report.name
-h2#toc Inhaltsverzeichnis
-nav
- = link_to(@report.name, "##{dom_id(@report)}")
- ul
- li = link_to("Inhaltsverzeichnis", "#toc")
- li
- = link_to('Testbericht')
- ul
- - @report.pages.select { |p| p.elements.any? { |e| e.success_criteria.any?(&:failed?) } }.each do |page|
- li
- = link_to("#{page.position} #{page.path}", "##{dom_id(page)}")
- ul
- - page.elements.select { |e| e.success_criteria.any?(&:failed?) }.each do |element|
- li
- = link_to("#{element.number} #{element.title}")
- ul
- - element.success_criteria.select(&:failed?).each do |sc|
- li = link_to("#{sc.number} #{sc.title}", "##{dom_id(sc)}")
- li
- = link_to("Anhang")
- ul
- - @failed_success_criteria.group_by(&:check).each do |check, scs|
- li = link_to(check.display_label)
+h2 1 Einschätzung
+p Gibt es hier Text?
+h3 1.1 Zielsetzung und Ausgangslage
+p Woher kommt dieser Text?
-h2 Testbericht
+h3 1.2 Wie wurde getestet
+p Woher kommt dieser Text?
+
+h3 1.3 Einschätzung
+p Woher kommt dieser Text?
+
+h2 2 Protokoll
+- current_page_pos = 0
+- current_abs_element_pos = 0
- @report.pages.select { |p| p.elements.any? { |e| e.success_criteria.any? { _1.failed? } } }.each do |page|
- h3 = "#{page.position} #{page.path}"
- - page.elements { |e| e.success_criteria.any? { _1.failed? } }.each do |element|
- h4 = "#{element.number} #{element.title}"
- - element.success_criteria.select{ _1.failed? }.each do |sc|
- h5 = "#{sc.number} #{sc.title}"
+ - current_page_pos += 1
+ - current_element_pos = 0
+ h3 = "2.#{current_page_pos} #{page.path}"
+ p
+ strong URL
+ = page.url
+ - page.elements.select { |e| e.success_criteria.any? { _1.failed? } }.each do |element|
+ - current_element_pos += 1
+ - current_abs_element_pos += 1
+ - current_sc_pos = 0
+ h4 = "2.#{current_page_pos}.#{current_element_pos} #{element.title}"
+ /h3 = "2.#{current_abs_element_pos} #{element.title}"
+ = safe_display(element.screenshot) { image_tag(_1.representation(resize_to_fit: [250, 250]))}
+ = element.description
+ - element.success_criteria.select(&:failed?).each do |sc|
+ - current_sc_pos += 1
+ /h4
+ = "2.#{current_abs_element_pos}.#{current_sc_pos} #{sc.title}"
+ h5 = "2.#{current_page_pos}.#{current_element_pos}.#{current_sc_pos} #{sc.title}"
+ p
+ strong Protokoll-Nummer
+ =< sc.number
- if sc.test_comment?
p = sc.test_comment
- dl
- dt Kriterium
- dd = sc.quick_criterion
- dt Fail
- dd = sc.quick_fail
- dt Fix
- dd = sc.quick_fix
- dt WCAG
- dd = link_to(sc.check.external_number, sc.check.external_url)
+ - safe_display(sc.quick_criterion) do
+ strong Kriterium
+ .body_text = _1
+ - safe_display(sc.quick_fail) do
+ strong Quick Fail
+ .body_text = _1
+ - safe_display(sc.quick_fix) do
+ strong Quick Fix
+ .body_text = _1
+ strong WCAG
+ .body_text = link_to(sc.check.external_number, sc.check.external_url)
-h2 Anhang
-
-h3 Liste der zu beachtenden WCAG Regeln
-
-- @failed_success_criteria.group_by(&:check).each do |check, scs|
- h4 = check.display_label
- = check.criterion_de
- strong Erfolgskriterien
- p = scs.map(&:number).join(", ")
+h2 3 Anhang: Liste der zu beachtenden WCAG Regeln
+- counter = 0
+- @failed_success_criteria.group_by(&:check).sort_by{ |c, scs| c.number }.each do |check, scs|
+ - counter += 1
+ h3 = "3.#{counter}. #{check.name_de}"
+ - safe_display(check.external_number) do
+ strong WCAG Nummer
+ .body_text = _1
+ - safe_display(check.external_url) do
+ strong WCAG Link
+ .body_text = _1
+ - safe_display(check.conformity_level) do
+ strong Konformität
+ .body_text = _1
+ - safe_display(check.conformity_notice_de) do
+ strong Anmerkung Konformität
+ .body_text = _1
+ - safe_display(check.priority) do
+ strong Priorität
+ .body_text = _1
+ - safe_display(check.criterion_de) do
+ strong Kriterium/Grundlage
+ .body_text = _1
+ - safe_display(check.exemption_details_de) do
+ strong Ausnahmen
+ .body_text = _1
+ - safe_display(check.criterion_details_de) do
+ strong Verstehen
+ .body_text = _1
+ - safe_display(check.example_de) do
+ strong Beispiel
+ .body_text = _1
+ - safe_display(check.annotation_de) do
+ strong Anmerkung
+ .body_text = _1
+ - if check.links.any?
+ strong Links
+ .body_text
+ - check.links.group_by(&:link_category).each do |category, links|
+ strong = category.t_name
+ ul
+ - links.each do |l|
+ li = link_to(l.text, l.url)
+ strong Erfolgskriterien
+ .body_text = scs.map(&:number).join(", ")
diff --git a/app/views/guidelines/_form.html.erb b/app/views/guidelines/_form.html.erb
new file mode 100644
index 0000000..d3c952a
--- /dev/null
+++ b/app/views/guidelines/_form.html.erb
@@ -0,0 +1,7 @@
+<%= bootstrap_form_with(model: guideline) do |form| %>
+ <%= form.collection_select :principle_id, Principle.all.sort_by(&:id), :id, :t_name %>
+ <%= form.number_field :number %>
+ <%= form.text_field :name_de %>
+ <%= form.rich_text_area :description_de %>
+ <%= form.submit %>
+<% end %>
diff --git a/app/views/guidelines/_guideline.html.erb b/app/views/guidelines/_guideline.html.erb
new file mode 100644
index 0000000..0560533
--- /dev/null
+++ b/app/views/guidelines/_guideline.html.erb
@@ -0,0 +1,15 @@
+
+
+ Principle:
+ <%= guideline.principle.t_name %>
+
+
+ <%= guideline.description_de %>
+
Richtlinien
+ <% guideline.checks.each do |check| %>
+
+ <%= link_to check %>
+ <%= check.t_criterion %>
+
+ <% end %>
+
diff --git a/app/views/guidelines/_guideline.json.jbuilder b/app/views/guidelines/_guideline.json.jbuilder
new file mode 100644
index 0000000..72c091d
--- /dev/null
+++ b/app/views/guidelines/_guideline.json.jbuilder
@@ -0,0 +1,2 @@
+json.extract! guideline, :id, :principle_id, :number, :name_de, :created_at, :updated_at
+json.url guideline_url(guideline, format: :json)
diff --git a/app/views/guidelines/edit.html.erb b/app/views/guidelines/edit.html.erb
new file mode 100644
index 0000000..2411616
--- /dev/null
+++ b/app/views/guidelines/edit.html.erb
@@ -0,0 +1,8 @@
+
<%= t("scaffold.pagetitle_edit", model: Guideline.model_name.human) %>
+
+<%= render "form", guideline: @guideline %>
+
+
+ <%= link_to t("scaffold.link_show", model: Guideline.model_name.human), @guideline %>
+ <%= link_to t("scaffold.link_index", model: Guideline.model_name.human(count: 2)), guidelines_path %>
+
diff --git a/app/views/guidelines/index.html.erb b/app/views/guidelines/index.html.erb
new file mode 100644
index 0000000..fe34cbf
--- /dev/null
+++ b/app/views/guidelines/index.html.erb
@@ -0,0 +1,28 @@
+
<%= t("scaffold.pagetitle_index", model: Guideline.model_name.human(count: 2)) %>
+
+
+
+
+
+ | <%= Guideline.human_attribute_name(:name_de) %> |
+
+ <%= Guideline.human_attribute_name(:description_de) %> |
+
+
+
+ <% @guidelines.each do |guideline| %>
+
+
+
+
+ | <%= link_to(guideline, url_for(guideline)) %> |
+ <%= link_to(guideline.description_de, url_for(guideline)) %> |
+
+
+ <% end %>
+
+
+
+
+ <%= link_to t("scaffold.link_new", model: Guideline.model_name.human), new_guideline_path %>
+
diff --git a/app/views/guidelines/index.json.jbuilder b/app/views/guidelines/index.json.jbuilder
new file mode 100644
index 0000000..cd94a2f
--- /dev/null
+++ b/app/views/guidelines/index.json.jbuilder
@@ -0,0 +1 @@
+json.array! @guidelines, partial: "guidelines/guideline", as: :guideline
diff --git a/app/views/guidelines/new.html.erb b/app/views/guidelines/new.html.erb
new file mode 100644
index 0000000..7e57546
--- /dev/null
+++ b/app/views/guidelines/new.html.erb
@@ -0,0 +1,7 @@
+
<%= t("scaffold.pagetitle_new", model: Guideline.model_name.human) %>
+
+<%= render "form", guideline: @guideline %>
+
+
+ <%= link_to t("scaffold.link_index", model: Guideline.model_name.human(count: 2)), guidelines_path %>
+
diff --git a/app/views/guidelines/show.html.erb b/app/views/guidelines/show.html.erb
new file mode 100644
index 0000000..7334fa3
--- /dev/null
+++ b/app/views/guidelines/show.html.erb
@@ -0,0 +1,9 @@
+
<%= @guideline %>
+
+<%= render @guideline %>
+
+
+ <%= link_to t("scaffold.link_edit", model: @guideline.model_name.human), edit_guideline_path(@guideline) %>
+ <%= link_to t("scaffold.link_index", model: @guideline.model_name.human(count: 2)), guidelines_path %>
+ <%= button_to t("scaffold.link_destroy", model: @guideline.model_name.human), @guideline, method: :delete, class: "btn btn-outline-danger" %>
+
diff --git a/app/views/guidelines/show.json.jbuilder b/app/views/guidelines/show.json.jbuilder
new file mode 100644
index 0000000..a0b1efe
--- /dev/null
+++ b/app/views/guidelines/show.json.jbuilder
@@ -0,0 +1 @@
+json.partial! "guidelines/guideline", guideline: @guideline
diff --git a/app/views/home/show.html.slim b/app/views/home/show.html.slim
index 345cd2b..2d5443c 100644
--- a/app/views/home/show.html.slim
+++ b/app/views/home/show.html.slim
@@ -1,30 +1,43 @@
-h1 a11ydive
-h2 Dashboard
+h1 Dashboard
-- if Report.any?
- h3 Zuletzt bearbeitete Prüfberichte
- ul
- - Report.all.order(updated_at: :desc).limit(3).each do |r|
- li = link_to(r.name, r)
+.row
+ .col-md-6
+ - if Project.current.any?
+ h2
+ i.bi.bi-folder>
+ 'Aktuelle Projekte
+ ul
+ - Project.current.order(updated_at: :desc).each do |p|
+ li = link_to(p.name, p)
-p
- i.bi.bi-journal-text
- =< Report.count
- =< link_to Report.model_name.human(count: Report.count), :reports
+ - if Report.any?
+ h2
+ i.bi.bi-journal-text>
+ 'Zuletzt bearbeitete Prüfberichte
+ ul
+ - Report.all.order(updated_at: :desc).limit(3).each do |r|
+ li = link_to(r.name, r)
-h3 Hotkeys
-p Auf der Bericht-Ausfüllen Seite können folgende Shortcuts verwendet werden:
-dl
- dt t
- dd Springe zum Anfang des Contents (Skip-Link, kann auf allen Seiten verwendet werden)
- dt a
- dd Alle auf
- dt s
- dd Alle zu
- dt b
- dd Baum
- dt n
- dd Notizen
- dt e
- dd Springe zu erstem Check
-
\ No newline at end of file
+ .col-md-6
+ h2 Browser Erweiterungen
+ p = link_to "Language Tools KI Korrektur", "https://languagetool.org/services#browsers"
+ p = link_to "DeepL Firefox Extension", "https://www.deepl.com/en/firefox-extension"
+ p = link_to "DeepL Chrome Extension", "https://www.deepl.com/en/chrome-extension"
+ p = link_to "DeepL Edge Extension", "https://www.deepl.com/en/edge-extension"
+
+ h2 Hotkeys
+ p Auf der Bericht-Ausfüllen Seite können folgende Shortcuts verwendet werden:
+ dl
+ dt t
+ dd Springe zum Anfang des Contents (Skip-Link, kann auf allen Seiten verwendet werden)
+ dt a
+ dd Alle auf
+ dt s
+ dd Alle zu
+ dt b
+ dd Baum
+ dt n
+ dd Notizen
+ dt e
+ dd Springe zu erstem Check
+
diff --git a/app/views/layouts/_toast.html.slim b/app/views/layouts/_toast.html.slim
new file mode 100644
index 0000000..600e969
--- /dev/null
+++ b/app/views/layouts/_toast.html.slim
@@ -0,0 +1,8 @@
+.toast class="#{alert ? "text-bg-danger" : "text-bg-info"}" role="alert" aria-live="assertive" aria-atomic="true" data={ controller: "toast", ts: Time.now.to_f }
+ .toast-header
+ /img src="..." class="rounded me-2" alt="...">
+ /strong.me-auto = heading
+ .small.me-auto = l(Time.current.to_time)
+ button.btn-close type="button" data-bs-dismiss="toast" aria-label="Schliessen"
+ .toast-body
+ = content
diff --git a/app/views/layouts/application.html.slim b/app/views/layouts/application.html.slim
index 18a65aa..a53d602 100644
--- a/app/views/layouts/application.html.slim
+++ b/app/views/layouts/application.html.slim
@@ -1,5 +1,5 @@
doctype html
-html data-bs-theme="#{cookies[:"modeTheme"] || "light"}" data-controller="set-theme"
+html lang=:de data-bs-theme="#{cookies[:"modeTheme"] || "light"}" data-controller="set-theme"
head
title a11ydive
meta[name="viewport" content="width=device-width,initial-scale=1"]
@@ -16,5 +16,11 @@ html data-bs-theme="#{cookies[:"modeTheme"] || "light"}" data-controller="set-th
main.col.ps-md-2.pt-2
#main-content[data-controller="rich-text-link-targets"]
= yield
- /footer.container-fluid.mt-auto.border-top
- = Rails.configuration.build_version && "Version: #{Rails.configuration.build_version}"
+
+ .toast-container.position-fixed.top-0.end-0.p-3 id="toasts"
+ - if flash.alert
+ = render partial: "layouts/toast", locals: { content: flash.alert, alert: true }
+ - if flash.notice
+ = render partial: "layouts/toast", locals: { content: flash.notice, alert: false }
+
+ = turbo_frame_tag "modal"
diff --git a/app/views/layouts/exports.html.slim b/app/views/layouts/exports.html.slim
index 28f8a3a..92cda65 100644
--- a/app/views/layouts/exports.html.slim
+++ b/app/views/layouts/exports.html.slim
@@ -1,12 +1,10 @@
doctype html
-html data-bs-theme="light" data-controller="set-theme"
+html
head
title a11ydive Export
meta[name="viewport" content="width=device-width,initial-scale=1"]
= csrf_meta_tags
= csp_meta_tag
- = stylesheet_link_tag "exports", "data-turbo-track": "reload"
- = javascript_include_tag "application", "data-turbo-track": "reload", type: "module"
body
- main#main-content
+ main.container#main-content
= yield
diff --git a/app/views/layouts/modal.html.slim b/app/views/layouts/modal.html.slim
new file mode 100644
index 0000000..4a3c12e
--- /dev/null
+++ b/app/views/layouts/modal.html.slim
@@ -0,0 +1,9 @@
+= turbo_frame_tag "modal" do
+ dialog.bg-body id="modal" data={ controller: :dialog }
+ .float-end
+ form method="dialog"
+ button.btn.btn-outline-danger
+ i.bi.bi-x-lg
+ = yield
+
+data-action="turbo:submit-end->turbo-modal#submitEnd"
diff --git a/app/views/pages/_form.html.slim b/app/views/pages/_form.html.slim
index 0d0beda..a909d1f 100644
--- a/app/views/pages/_form.html.slim
+++ b/app/views/pages/_form.html.slim
@@ -2,4 +2,5 @@
= form.text_field :path
= form.text_field :url
= form.submit
- = link_to("Abbrechen", report_path(@page.report), class: "btn btn-outline-secondary")
+ - unless modal?
+ = link_to("Abbrechen", report_path(@page.report), class: "btn btn-outline-secondary")
diff --git a/app/views/pages/_page.html.erb b/app/views/pages/_page.html.erb
index 3505c40..7fa2aa0 100644
--- a/app/views/pages/_page.html.erb
+++ b/app/views/pages/_page.html.erb
@@ -11,5 +11,5 @@
<% end %>
- <%= link_to("Sprinte zum ersten Element", "##{dom_id(page.elements.first)}", class: "visually-hidden", data: {controller: :hotkey, hotkey: "e", turbo: false}) if page.elements.first %>
+ <%= link_to("Springe zum ersten Element", "##{dom_id(page.elements.first)}", class: "visually-hidden", data: {controller: :hotkey, hotkey: "e", turbo: false}) if page.elements.first %>
diff --git a/app/views/pages/edit.html.erb b/app/views/pages/edit.html.erb
index 6983a18..f809d03 100644
--- a/app/views/pages/edit.html.erb
+++ b/app/views/pages/edit.html.erb
@@ -2,7 +2,9 @@
<%= render "form", page: @page %>
+<% unless modal? %>
<%= link_to t("scaffold.link_show", model: Page.model_name.human), @page %>
<%= link_to t("scaffold.link_index", model: Page.model_name.human(count: 2)), report_pages_path(@page.report) %>
+<% end %>
diff --git a/app/views/pages/show.html.slim b/app/views/pages/show.html.slim
index c2c8f8b..d5045b1 100644
--- a/app/views/pages/show.html.slim
+++ b/app/views/pages/show.html.slim
@@ -11,7 +11,8 @@ h2
= turbo_frame_tag(dom_id(@page, :notes)) do
= render partial: "pages/notes", locals: { page: @page }
-.action-row
- = link_to t("scaffold.link_edit", model: @page.model_name.human), edit_page_path(@page)
- = link_to t("scaffold.link_index", model: @page.model_name.human(count: 2)), report_pages_path(@page.report)
- = button_to t("scaffold.link_destroy", model: @page.model_name.human), @page, method: :delete, class: "btn btn-outline-danger"
+- unless modal?
+ .action-row
+ = link_to t("scaffold.link_edit", model: @page.model_name.human), edit_page_path(@page)
+ = link_to t("scaffold.link_index", model: @page.model_name.human(count: 2)), report_pages_path(@page.report)
+ = button_to t("scaffold.link_destroy", model: @page.model_name.human), @page, method: :delete, class: "btn btn-outline-danger"
diff --git a/app/views/pages/update.turbo_stream.slim b/app/views/pages/update.turbo_stream.slim
index 298fcff..6bad9ea 100644
--- a/app/views/pages/update.turbo_stream.slim
+++ b/app/views/pages/update.turbo_stream.slim
@@ -4,4 +4,6 @@
= turbo_stream.update dom_id(element, :title), "#{element.page.position}.#{element.position} #{element.title}"
= turbo_stream.replace dom_id(element, :page_nav_row), partial: "elements/page_nav_row", locals: { element: element, current_page: element.page == @page}
- element.success_criteria.each do |sc|
- = turbo_stream.update dom_id(sc, :position), "#{sc.page.position}.#{sc.element.position}.#{sc.position}"
\ No newline at end of file
+ = turbo_stream.update dom_id(sc, :position), "#{sc.page.position}.#{sc.element.position}.#{sc.position}"
+
+= turbo_stream_toast("Pfad gespeichert", false)
\ No newline at end of file
diff --git a/app/views/projects/_form.html.erb b/app/views/projects/_form.html.erb
new file mode 100644
index 0000000..5bbeee4
--- /dev/null
+++ b/app/views/projects/_form.html.erb
@@ -0,0 +1,5 @@
+<%= bootstrap_form_with(model: project) do |form| %>
+ <%= form.text_field :name %>
+ <%= form.rich_text_area :details %>
+ <%= form.submit %>
+<% end %>
diff --git a/app/views/projects/_project.html.slim b/app/views/projects/_project.html.slim
new file mode 100644
index 0000000..5e098c9
--- /dev/null
+++ b/app/views/projects/_project.html.slim
@@ -0,0 +1,20 @@
+.project id=dom_id(project)
+ p
+ strong Name:
+ = project.name
+ p
+ strong Details:
+ = project.details
+ p
+ strong Berichte:
+ ul.ps-0
+ - project.reports.each do
+ li.d-flex.ps-0
+ =< "ID #{_1.id}: #{l(_1.created_at,format: :short)} #{_1.name}"
+ = link_to(_1, class: "btn btn-sm btn-link-secondary") do
+ i.bi.bi-folder-symlink
+ = button_to(project_reports_path(project), class: "btn btn-sm btn-link-secondary", params: { copy_from_id: _1.id }) do
+ i.bi.bi-copy
+ p
+ = link_to(new_project_report_path(project), class: "btn btn-secondary") do
+ i.bi.bi-plus-lg
diff --git a/app/views/projects/_project.json.jbuilder b/app/views/projects/_project.json.jbuilder
new file mode 100644
index 0000000..c1f8d9f
--- /dev/null
+++ b/app/views/projects/_project.json.jbuilder
@@ -0,0 +1,2 @@
+json.extract! project, :id, :name, :created_at, :updated_at
+json.url project_url(project, format: :json)
diff --git a/app/views/projects/edit.html.erb b/app/views/projects/edit.html.erb
new file mode 100644
index 0000000..ee36a94
--- /dev/null
+++ b/app/views/projects/edit.html.erb
@@ -0,0 +1,8 @@
+<%= t("scaffold.pagetitle_edit", model: Project.model_name.human) %>
+
+<%= render "form", project: @project %>
+
+
+ <%= link_to t("scaffold.link_show", model: Project.model_name.human), @project %>
+ <%= link_to t("scaffold.link_index", model: Project.model_name.human(count: 2)), projects_path %>
+
diff --git a/app/views/projects/index.html.erb b/app/views/projects/index.html.erb
new file mode 100644
index 0000000..c487887
--- /dev/null
+++ b/app/views/projects/index.html.erb
@@ -0,0 +1,25 @@
+<%= t("scaffold.pagetitle_index", model: Project.model_name.human(count: 2)) %>
+
+
+
+
+ | <%= Project.human_attribute_name(:id) %> |
+
+ <%= Project.human_attribute_name(:name) %> |
+
+
+
+ <% @projects.each do |project| %>
+
+ | <%= link_to(project.id, url_for(project)) %> |
+
+ <%= link_to(project.name, url_for(project)) %> |
+
+
+ <% end %>
+
+
+
+
+ <%= link_to t("scaffold.link_new", model: Project.model_name.human), new_project_path %>
+
\ No newline at end of file
diff --git a/app/views/projects/index.json.jbuilder b/app/views/projects/index.json.jbuilder
new file mode 100644
index 0000000..e9db4f9
--- /dev/null
+++ b/app/views/projects/index.json.jbuilder
@@ -0,0 +1 @@
+json.array! @projects, partial: "projects/project", as: :project
diff --git a/app/views/projects/new.html.erb b/app/views/projects/new.html.erb
new file mode 100644
index 0000000..4876968
--- /dev/null
+++ b/app/views/projects/new.html.erb
@@ -0,0 +1,7 @@
+<%= t("scaffold.pagetitle_new", model: Project.model_name.human) %>
+
+<%= render "form", project: @project %>
+
+
+ <%= link_to t("scaffold.link_index", model: Project.model_name.human(count: 2)), projects_path %>
+
diff --git a/app/views/projects/show.html.erb b/app/views/projects/show.html.erb
new file mode 100644
index 0000000..16d830f
--- /dev/null
+++ b/app/views/projects/show.html.erb
@@ -0,0 +1,9 @@
+<%= t("scaffold.pagetitle_show", model: @project.class.model_name.human) %>
+
+<%= render @project %>
+
+
+ <%= link_to t("scaffold.link_edit", model: @project.model_name.human), edit_project_path(@project) %>
+ <%= link_to t("scaffold.link_index", model: @project.model_name.human(count: 2)), projects_path %>
+ <%= button_to t("scaffold.link_destroy", model: @project.model_name.human), @project, method: :delete, class: "btn btn-outline-danger" if @project.reports.none? %>
+
diff --git a/app/views/projects/show.json.jbuilder b/app/views/projects/show.json.jbuilder
new file mode 100644
index 0000000..0be99bd
--- /dev/null
+++ b/app/views/projects/show.json.jbuilder
@@ -0,0 +1 @@
+json.partial! "projects/project", project: @project
diff --git a/app/views/reports/_form.html.erb b/app/views/reports/_form.html.erb
index 23a58a6..bea1172 100644
--- a/app/views/reports/_form.html.erb
+++ b/app/views/reports/_form.html.erb
@@ -1,4 +1,5 @@
-<%= bootstrap_form_with(model: report) do |form| %>
+<%= bootstrap_form_with(model: report.persisted? ? report : [@project, report]) do |form| %>
+ <%= form.collection_select :project_id, Project.all, :id, :name, include_blank: true %>
<%= form.text_field :name %>
<%= form.text_field :url %>
<%= form.rich_text_area :comment %>
diff --git a/app/views/reports/edit.html.erb b/app/views/reports/edit.html.erb
index 40ee203..7c43fd4 100644
--- a/app/views/reports/edit.html.erb
+++ b/app/views/reports/edit.html.erb
@@ -4,5 +4,5 @@
<%= link_to t("scaffold.link_show", model: Report.model_name.human), @report %>
- <%= link_to t("scaffold.link_index", model: Report.model_name.human(count: 2)), reports_path %>
+ <%= link_to t("scaffold.link_index", model: Report.model_name.human(count: 2)), project_reports_path(@report.project) %>
diff --git a/app/views/reports/index.html.erb b/app/views/reports/index.html.erb
index 61b1a89..af5baf5 100644
--- a/app/views/reports/index.html.erb
+++ b/app/views/reports/index.html.erb
@@ -27,5 +27,5 @@
- <%= link_to t("scaffold.link_new", model: Report.model_name.human), new_report_path %>
+ <%= link_to t("scaffold.link_new", model: Report.model_name.human), new_project_report_path(@project) %>
diff --git a/app/views/reports/new.html.erb b/app/views/reports/new.html.erb
index cc21f9b..61d6d54 100644
--- a/app/views/reports/new.html.erb
+++ b/app/views/reports/new.html.erb
@@ -3,5 +3,5 @@
<%= render "form", report: @report %>
- <%= link_to t("scaffold.link_index", model: Report.model_name.human(count: 2)), reports_path %>
+ <%= link_to t("scaffold.link_index", model: Report.model_name.human(count: 2)), project_reports_path(@project) %>
diff --git a/app/views/reports/show.html.slim b/app/views/reports/show.html.slim
index 13f31c0..03cce27 100644
--- a/app/views/reports/show.html.slim
+++ b/app/views/reports/show.html.slim
@@ -1,29 +1,32 @@
+.border-bottom.mb-3
+ h1
+ i.bi.bi-journal-text.me-2
+ = @report.name
div
- small.float-end
- | Erstellt am
- = l(@report.created_at, format: :short)
- | , zuletzt bearbeitet am
- = l(@report.updated_at, format: :short)
-h1
- i.bi.bi-journal-text.me-2
- = @report.name
-- if @report.comment
- .smb-4.lead.mb-3
- = @report.comment
+ small = "Erstellt am #{l(@report.created_at, format: :short)}, zuletzt bearbeitet am #{l(@report.updated_at, format: :short)}"
+
+p
+ i.bi.bi-folder
+ strong< = link_to(@report.project.name, @report.project)
+
+.smb-4.lead.mb-5
+ = @report.comment || tag.i("leer")
- if @current_page
- h2
- i.bi.bi-file-earmark-check
- =< @current_page.position
- =< @current_page.path
- p
- 'URL:
- = safe_display(@current_page.full_url) { link_to(_1, _1, target: :_blank) }
- p.actions
- .d-flex.justify-content-end data-controller="details-list" data-target-id="element_list"
- .btn-group.me-3
- = link_to("Alle zu [s]", "#", data: { action: "click->details-list#closeAll", controller: :hotkey, hotkey: "s" }, class: "btn btn-outline-secondary")
- = link_to("Alle auf [a]", "#", data: { action: "click->details-list#openAll", controller: :hotkey, hotkey: "a" }, class: "btn btn-outline-secondary")
- = button_to(tag.i(class: "bi bi-trash"), page_path(@current_page), method: :delete, class: "btn btn-outline-danger", form: {data: { turbo_confirm: "Bist du sicher?" }})
+ .current_page data-controller="details-list" data-target-id="element_list"
+ .border-bottom.mb-3.d-flex
+ h2
+ i.bi.bi-file-earmark-check
+ =< @current_page.position
+ =< @current_page.path
+ = page_menu(@current_page)
+ p
+ 'URL:
+ = safe_display(@current_page.full_url) { link_to(_1, _1, target: :_blank) }
+ p.actions
+ .d-flex.justify-content-end
+ .btn-group.me-3.visually-hidden
+ = link_to("Alle zu [s]", "#", data: { action: "click->details-list#closeAll", controller: :hotkey, hotkey: "s" }, class: "btn btn-outline-secondary")
+ = link_to("Alle auf [a]", "#", data: { action: "click->details-list#openAll", controller: :hotkey, hotkey: "a" }, class: "btn btn-outline-secondary")
.row
.col-lg-3.col-md-4.col-sm-12
.page_nav.sticky-top
@@ -40,9 +43,9 @@ h1
= link_to(report_export_path(@report), class: "btn btn-secondary", target: :_blank) do
i.bi.bi-filetype-html
| Online HTML
- / = link_to report_path(@report, format: :pdf), class: "btn btn-secondary", target: "_blank" do
- / i.bi.bi-filetype-pdf
- / | PDF
+ = link_to report_path(@report, format: :pdf), class: "btn btn-secondary", target: "_blank" do
+ i.bi.bi-filetype-pdf
+ | PDF
/ = link_to report_path(@report, format: :docx), class: "btn btn-secondary", target: "_blank" do
/ i.bi.bi-filetype-docx
/ | DOCX
@@ -60,5 +63,5 @@ h1
| ODT
.action-row
= link_to t("scaffold.link_edit", model: @report.model_name.human), edit_report_path(@report)
- = link_to t("scaffold.link_index", model: @report.model_name.human(count: 2)), reports_path
- = button_to t("scaffold.link_destroy", model: @report.model_name.human), @report, method: :delete, class: "btn btn-outline-danger"
+ = link_to t("scaffold.link_index", model: @report.model_name.human(count: 2)), project_reports_path(@report.project)
+ = button_to t("scaffold.link_destroy", model: @report.model_name.human), @report, method: :delete, class: "btn btn-outline-danger", data: { turbo_confirm: "Bist du sicher?"}
diff --git a/app/views/success_criteria/_body.html.slim b/app/views/success_criteria/_body.html.slim
index 59bf000..7da29c1 100644
--- a/app/views/success_criteria/_body.html.slim
+++ b/app/views/success_criteria/_body.html.slim
@@ -1,19 +1,21 @@
.content id="#{dom_id(success_criterion, :body)}"
= turbo_frame_tag(dom_id(success_criterion, :frame)) do
- .row
- .col
- .my-3.btn-group[role="group" aria-label="Resultat"]
- = bootstrap_form_with(model: success_criterion, data: { controller: "autosubmit" }) do |form|
- = form.radio_button_without_bootstrap :result, :passed, class: "btn-check", autocomplete: "off", id: dom_id(success_criterion, :result_passed)
- label.btn.btn-outline-success for=dom_id(success_criterion, :result_passed) Bestanden
- = form.radio_button_without_bootstrap :result, :failed, class: "btn-check", autocomplete: "off", id: dom_id(success_criterion, :result_failed)
- label.btn.btn-outline-danger for=dom_id(success_criterion, :result_failed) Durchgefallen
- = form.radio_button_without_bootstrap :result, :not_applicable, class: "btn-check", autocomplete: "off", id: dom_id(success_criterion, :result_not_applicable)
- label.btn.btn-outline-secondary for=dom_id(success_criterion, :result_not_applicable) Nicht anwendbar
- /= form.radio_button_without_bootstrap :result, nil, class: "btn-check", autocomplete: "off", id: dom_id(success_criterion, :result_not_applicable)
- /label.btn.btn-outline-secondary for=dom_id(success_criterion, :nil) Reset
- = button_to(tag.i(class: "bi bi-trash"), success_criterion, method: :delete, class: "btn btn-link text-danger", data: { turbo_confirm: "Bist du sicher?"})
- = success_criterion_edit_button(success_criterion, false)
+ .d-flex
+ .my-3.btn-group[role="group" aria-label="Resultat"]
+ = bootstrap_form_with(model: success_criterion, data: { controller: "autosubmit" }) do |form|
+ = form.radio_button_without_bootstrap :result, :passed, class: "btn-check", autocomplete: "off", id: dom_id(success_criterion, :result_passed)
+ label.btn.btn-outline-success for=dom_id(success_criterion, :result_passed) Bestanden
+ = form.radio_button_without_bootstrap :result, :failed, class: "btn-check", autocomplete: "off", id: dom_id(success_criterion, :result_failed)
+ label.btn.btn-outline-danger for=dom_id(success_criterion, :result_failed) Durchgefallen
+ = form.radio_button_without_bootstrap :result, :not_applicable, class: "btn-check", autocomplete: "off", id: dom_id(success_criterion, :result_not_applicable)
+ label.btn.btn-outline-secondary for=dom_id(success_criterion, :result_not_applicable) Nicht anwendbar
+ /= form.radio_button_without_bootstrap :result, nil, class: "btn-check", autocomplete: "off", id: dom_id(success_criterion, :result_not_applicable)
+ /label.btn.btn-outline-secondary for=dom_id(success_criterion, :nil) Reset
+ - unless success_criterion.test_comment.blank?
+ = link_to(edit_comment_success_criterion_path(success_criterion), class: "btn btn-outline-warning my-3 ms-3", data: { turbo_frame: "modal" }) do
+ i.bi.bi-chat>
+ 'Kommentar bearbeiten
+ = success_criterion_menu(success_criterion)
.row
.col
- if success_criterion.test_comment?
@@ -45,7 +47,7 @@
.text-end.fw-bold = SuccessCriterion.human_attribute_name(:quick_fix)
.col-md-8.col-lg-9
= success_criterion.quick_fix
- .row.mb-3
+ .row
.col-md-4.col-lg-3
.text-end.fw-bold = SuccessCriterion.human_attribute_name(:test_instructions)
.col-md-8.col-lg-9
diff --git a/app/views/success_criteria/_form.html.erb b/app/views/success_criteria/_form.html.erb
deleted file mode 100644
index 8f351a1..0000000
--- a/app/views/success_criteria/_form.html.erb
+++ /dev/null
@@ -1,11 +0,0 @@
-
- <%= bootstrap_form_with(model: success_criterion.persisted? ? success_criterion : [:element, success_criterion], data: { controller: "unsaved-changes" }) do |form| %>
- <%= form.text_field :title %>
- <%= form.collection_select :result, SuccessCriterion.results.keys.map { [_1, t("activerecord.attributes.success_criterion.results/#{_1}")] }, :first, :second, include_blank: success_criterion.result ? "(Resultat zurücksetzen)" : "(unbeantwortet)" %>
- <%= form.rich_text_area :quick_criterion %>
- <%= form.rich_text_area :quick_fail %>
- <%= form.rich_text_area :quick_fix %>
- <%= form.rich_text_area :test_comment %>
- <%= form.submit class: "btn btn-primary" %>
- <%= link_to "Abbrechen", success_criterion.persisted? ? success_criterion : success_criterion.element, class: "btn btn-outline-secondary" %>
- <% end %>
diff --git a/app/views/success_criteria/_form.html.slim b/app/views/success_criteria/_form.html.slim
new file mode 100644
index 0000000..b459173
--- /dev/null
+++ b/app/views/success_criteria/_form.html.slim
@@ -0,0 +1,11 @@
+= bootstrap_form_with(model: success_criterion.persisted? ? success_criterion : [:element, success_criterion], data: { controller: "unsaved-changes" }) do |form|
+ = form.text_field :title
+ = form.collection_select :result, SuccessCriterion.results.keys.map { [_1, t("activerecord.attributes.success_criterion.results/#{_1}")] }, :first, :second, include_blank: success_criterion.result ? "(Resultat zurücksetzen)" : "(unbeantwortet)"
+ = form.rich_text_area :quick_criterion
+ = form.rich_text_area :quick_fail
+ = form.rich_text_area :quick_fix
+ = form.rich_text_area :test_comment
+ = form.submit class: "btn btn-primary"
+- unless modal?
+ p Not MODAL
+ =< link_to "Abbrechen", success_criterion.persisted? ? success_criterion : success_criterion.element, class: "btn btn-outline-secondary"
diff --git a/app/views/success_criteria/_header.html.slim b/app/views/success_criteria/_header.html.slim
index a27c7be..b7a2fa6 100644
--- a/app/views/success_criteria/_header.html.slim
+++ b/app/views/success_criteria/_header.html.slim
@@ -3,7 +3,7 @@ summary.d-flex.align-items-start id=dom_id(success_criterion, :header)
.content.d-flex.align-items-center.w-100
.result-icon.flex-shrink-0 class=[success_criterion_result_color_classes(success_criterion)]
span.h1.bi class=[success_criterion_result_icon_classes(success_criterion)]
- .flex-fill
+ .flex-fill.py-1
span id=dom_id(success_criterion, :position)
= success_criterion.page.position
| .
@@ -19,4 +19,4 @@ summary.d-flex.align-items-start id=dom_id(success_criterion, :header)
= success_criterion_badge(success_criterion.check.external_number, extra_classes: "text-bg-info me-1")
= success_criterion_badge(success_criterion.level, extra_classes: "sc-level-#{success_criterion.level.to_s.downcase} me-1")
- i.bi.bi-grip-vertical.handle
\ No newline at end of file
+ i.bi.bi-grip-vertical.handle.me-1
diff --git a/app/views/success_criteria/_record_menu.html.slim b/app/views/success_criteria/_record_menu.html.slim
new file mode 100644
index 0000000..5524b70
--- /dev/null
+++ b/app/views/success_criteria/_record_menu.html.slim
@@ -0,0 +1,3 @@
+ = dropdown_menu(klass: "mt-3 ms-auto b-0") do
+ = success_criterion_edit_button(@success_criterion, true)
+ = button_to(tag.i(class: "bi bi-trash") + " Löschen".html_safe, @success_criterion, method: :delete, class: "text-danger", data: { turbo_confirm: "Bist du sicher?"})
diff --git a/app/views/success_criteria/destroy.turbo_stream.slim b/app/views/success_criteria/destroy.turbo_stream.slim
index 6848f33..f373009 100644
--- a/app/views/success_criteria/destroy.turbo_stream.slim
+++ b/app/views/success_criteria/destroy.turbo_stream.slim
@@ -1,4 +1,6 @@
= turbo_stream.remove dom_id(@success_criterion)
- @success_criterion.element.success_criteria.reject { _1 == @success_criterion }.each do |sc|
- Rails.logger.debug "Send to sc #{sc.id}"
- = turbo_stream.update dom_id(sc, :position), "#{sc.page.position}.#{sc.element.position}.#{sc.position}"
\ No newline at end of file
+ = turbo_stream.update dom_id(sc, :position), "#{sc.page.position}.#{sc.element.position}.#{sc.position}"
+
+= turbo_stream_toast("Erfolgskriterium wurde gelöscht", true)
diff --git a/app/views/success_criteria/edit.html.erb b/app/views/success_criteria/edit.html.erb
deleted file mode 100644
index f0093e8..0000000
--- a/app/views/success_criteria/edit.html.erb
+++ /dev/null
@@ -1,10 +0,0 @@
-<%= t("scaffold.pagetitle_edit", model: SuccessCriterion.model_name.human) %>
-
-<%= turbo_frame_tag(dom_id(@success_criterion, :frame)) do %>
- <%= render "form", success_criterion: @success_criterion %>
-<% end %>
-
-
- <%= link_to t("scaffold.link_show", model: SuccessCriterion.model_name.human), @success_criterion %>
- <%= link_to t("scaffold.link_index", model: SuccessCriterion.model_name.human(count: 2)), element_success_criteria_path(@success_criterion.element) %>
-
diff --git a/app/views/success_criteria/edit.html.slim b/app/views/success_criteria/edit.html.slim
new file mode 100644
index 0000000..e1a2a31
--- /dev/null
+++ b/app/views/success_criteria/edit.html.slim
@@ -0,0 +1,7 @@
+h2 Erfolgskriterium bearbeiten
+.mb-3
+ = render "form", success_criterion: @success_criterion
+- unless modal?
+ .action-row
+ = link_to t("scaffold.link_show", model: SuccessCriterion.model_name.human), @success_criterion
+ = link_to t("scaffold.link_index", model: SuccessCriterion.model_name.human(count: 2)), element_success_criteria_path(@success_criterion.element)
diff --git a/app/views/success_criteria/edit_comment.html.slim b/app/views/success_criteria/edit_comment.html.slim
new file mode 100644
index 0000000..46f1f06
--- /dev/null
+++ b/app/views/success_criteria/edit_comment.html.slim
@@ -0,0 +1,6 @@
+h2 Kommentar bearbeiten
+= bootstrap_form_with(model: @success_criterion.persisted? ? @success_criterion : [:element, @success_criterion], data: { controller: "unsaved-changes" }) do |form|
+ = form.rich_text_area :test_comment, hide_label: true
+ = form.submit class: "btn btn-primary"
+- unless modal?
+ =< link_to "Abbrechen", @success_criterion.persisted? ? @success_criterion : @success_criterion.element, class: "btn btn-outline-secondary"
diff --git a/app/views/success_criteria/update.turbo_stream.slim b/app/views/success_criteria/update.turbo_stream.slim
index 72fe6ae..c6e53ff 100644
--- a/app/views/success_criteria/update.turbo_stream.slim
+++ b/app/views/success_criteria/update.turbo_stream.slim
@@ -2,4 +2,5 @@
= turbo_stream.replace dom_id(@success_criterion, :body), partial: "success_criteria/body", locals: {success_criterion: @success_criterion }
- @success_criterion.element.success_criteria.each do |sc|
- = turbo_stream.update(dom_id(sc, :position), sc.number)
\ No newline at end of file
+ = turbo_stream.update(dom_id(sc, :position), sc.number)
+= turbo_stream_toast("Erfolgskriterium gespeichert: #{t("activerecord.attributes.success_criterion.results/#{@success_criterion.result}")}", false)
diff --git a/bin/build b/bin/build
new file mode 100755
index 0000000..31c1d20
--- /dev/null
+++ b/bin/build
@@ -0,0 +1,70 @@
+#!/usr/bin/env bash
+
+server=phela
+
+# Save current stash state
+initial_stash_count=$(git stash list | wc -l)
+
+# Check if working directory is clean
+if [[ -n $(git status --porcelain) ]]; then
+ echo "Repository is dirty. Stashing changes..."
+ git stash push --include-untracked --quiet
+ stashed=true
+else
+ echo "Repository is clean."
+ stashed=false
+fi
+
+if [[ -n "$1" ]]; then
+ tag="$1"
+else
+ tag=$(git describe --tags --exact-match 2>/dev/null)
+fi
+
+if [[ -n $tag ]]; then
+ echo "Current Git tag: $tag"
+else
+ branch=$(git rev-parse --abbrev-ref HEAD)
+ tag=$branch-$(git rev-parse HEAD)
+ echo "Current commit SHA-1: $tag"
+fi
+
+baseimage=code.hohl.cloud/jwa11y/a11yist
+image=$baseimage:$tag
+
+echo "Building tag $image"
+docker build --progress quiet -t $image --target release .
+
+
+# Restore the stash if we stashed
+if [ "$stashed" = true ]; then
+ echo "Restoring stashed changes..."
+ current_stash_count=$(git stash list | wc -l)
+ if (( current_stash_count > initial_stash_count )); then
+ git stash pop --quiet
+ echo "Changes restored."
+ else
+ echo "No stash to restore."
+ fi
+else
+ echo "No changes to restore."
+fi
+
+echo "Pushing image $image"
+docker push --quiet $image
+
+read -p "Do you want to SSH into $server and run 'deploy'? [y/N] " answer
+if [[ "$answer" =~ ^[Yy]$ ]]; then
+ echo "Connecting to $server and running 'deploy'..."
+ baseimage_esc=$(echo $baseimage | sed 's/\//\\\//g' | sed 's/\./\\\./g')
+ tag_esc=$(echo $image | sed 's/\//\\\//g' | sed 's/\./\\\./g')
+ read -r -d '' remote_script <> deployments.log
+REMOTE
+ echo "Execute deployment"
+ echo "$remote_script" | ssh "$server" "bash -s"
+fi
+
diff --git a/bin/dev b/bin/dev
index edcb0e0..eda330c 100755
--- a/bin/dev
+++ b/bin/dev
@@ -8,4 +8,4 @@ fi
# Default to port 3000 if not specified
export PORT="${PORT:-3000}"
-exec foreman start -f /app/Procfile.dev "$@"
+exec foreman start -f Procfile.dev "$@"
diff --git a/bin/dev_entrypoint b/bin/dev_entrypoint
new file mode 100755
index 0000000..1ca3bf7
--- /dev/null
+++ b/bin/dev_entrypoint
@@ -0,0 +1,8 @@
+#!/bin/bash
+
+if [ -f tmp/pids/server.pid ]; then
+ rm tmp/pids/server.pid
+fi
+
+exec "$@"
+
diff --git a/bin/docker-entrypoint b/bin/docker-entrypoint
index 67ef493..f89fe81 100755
--- a/bin/docker-entrypoint
+++ b/bin/docker-entrypoint
@@ -1,8 +1,24 @@
#!/bin/bash -e
+echo "entrypoint docker: ${@} ${ASSETS_PATH} :: ${@: 1:1} / ${@: 2:1}"
+
# If running the rails server then create or migrate existing database
-if [ "${1}" == "./bin/rails" ] && [ "${2}" == "server" ]; then
+if [ "${@: 1:1}" == "./bin/rails" ] && [ "${@: 2:1}" == "server" ]; then
+ if [ -f ${INSTALL_DIR}/pids/server.pid ]; then
+ rm ${INSTALL_DIR}/pids/server.pid
+ fi
+
+ echo "Prepare db..."
./bin/rails db:prepare
+
+ echo "Copy assets to <$ASSETS_PATH>?"
+
+ if [[ -n "$ASSETS_PATH" ]]; then
+ echo "Copy assets to $ASSETS_PATH"
+ find "$INSTALL_DIR/public" -mindepth 1 -exec echo "copy " {} \;
+ find "$INSTALL_DIR/public" -mindepth 1 -exec cp -a {} "$ASSETS_PATH" \;
+ fi
fi
+
exec "${@}"
diff --git a/bin/jobs b/bin/jobs
new file mode 100755
index 0000000..dcf59f3
--- /dev/null
+++ b/bin/jobs
@@ -0,0 +1,6 @@
+#!/usr/bin/env ruby
+
+require_relative "../config/environment"
+require "solid_queue/cli"
+
+SolidQueue::Cli.start(ARGV)
diff --git a/compose.yml b/compose.yml
new file mode 100644
index 0000000..964fd9a
--- /dev/null
+++ b/compose.yml
@@ -0,0 +1,59 @@
+# This is available in $COMPOSE_PROJECT_NAME
+name: a11yist
+
+networks:
+ ingress:
+ external: true
+
+services:
+ app: &app
+ build:
+ context: .
+ target: development
+ args:
+ NAME: ${USER}
+ UID: 1000
+ GID: 1000
+ INSTALL_DIR: ${PWD}
+ volumes:
+ - ${SSH_AUTH_SOCK}:/ssh-agent
+ - ${PWD}:${PWD}
+ env_file:
+ - .env
+ environment:
+ APP_HOST: ${COMPOSE_PROJECT_NAME}.localhost
+ HISTFILE: /app/tmp/.bash_history
+ IRBRC: /app/.irbrc
+ LOG_LEVEL: debug
+ PSQL_HISTORY: /app/tmp/.psql_history
+ RAILS_ENV: development
+ RAILS_SERVE_STATIC_FILES: 1
+ SELENIUM_REMOTE_URL: http://chrome:4444/wd/hub
+ SSH_AUTH_SOCK: /ssh-agent
+ TRUSTED_IP: 172.16.0.0/12,192.168.0.0/16,10.0.0.0/24
+ labels:
+ caddy: "http://${COMPOSE_PROJECT_NAME}.localhost"
+ caddy.reverse_proxy: "{{upstreams 3000}}"
+ networks:
+ - ingress
+ - default
+
+ edit:
+ <<: *app
+ restart: "no"
+ labels: []
+ depends_on: []
+ command: [ "hx", "." ]
+ entrypoint: null
+ networks:
+ - default
+
+ chrome:
+ image: selenium/standalone-chrome
+ shm_size: 2g
+ labels:
+ caddy: "http://browser.${COMPOSE_PROJECT_NAME}.localhost"
+ caddy.reverse_proxy: "{{upstreams 7900}}"
+ networks:
+ - ingress
+ - default
diff --git a/config/credentials.yml.enc b/config/credentials.yml.enc
index 7741360..d5e9f74 100644
--- a/config/credentials.yml.enc
+++ b/config/credentials.yml.enc
@@ -1 +1 @@
-vRtWWWCynlFuZljZsCQOV5D6xZlwp/LkuGZ2bPp1IuZiCRfJ2F8CXbubRavkqM0xxpHWkC7hiQ0lSv/dCPtaujG+aJ2Q0+KSw81kJ3xiYd/AiR3ZxO9prk5Zsf0LPLoONGBbYurJIb37hAWQ7h1r1qORLbtQGLb9pYlynObhXvkaYQR5E7Jr0Rcnon0d2uKJ13ukDAHUiIgwCE5/f+Y6UVllTLBCk0a+YDZvkv7xsYNpTTD9bgjpAU/pg6jv1xY0k/gZ8SFRsSQaJs8CYtbhMsyZBvImtguGfc7U7B4cFrgdzUPY473vBKBqm6O0StNagS5muP3/YLLN7xcrRDTBi9n3qllATlfJ9cxZ+JCWZJmyqINI4X+T/sc3lpzlo/grW0W+HwQ/4CZ3LkCN/OOqZlG1HL1u--NhnYNqgGpqSnh7Ut--KGndHl8kyj/uAjRG12R3zg==
\ No newline at end of file
+TjpgJe/DwNAzOraDbzXUo20hxCLkOn72DlXYkIouG0crCD3m4/LAiwDOlOWwsCO5Je6FzqKZniLUqSfVthChxewvZn+PY7XGTLECbB9gjSpRC6hERUxKIirLot+CH7lkMlM3f4o3NPf2I4vs8j6hooXcc8Vd8l1uMHOU1RHd+8EfPmTetqd0IETnEUdXigL50yjcbpxy8jHGdaeA8hHU3F+jwk7gRv11uVgEfn069qD9tc5AlAFWdnYJj/ZadAX2+bimHyne5Y12gmRAiqu95KXzUs0OlI+Vx9lpFyMQNacuKPPx0AeeBafjnMBozXOSU7MMCBUGzig07Kg+/tJSiekeLX0X2VEj3Ecqe9nL54fAGVSqJmwT19KvjeS4WfjvFDff9KAY4H+vKzfkBQzMFOTJjnMTNHa+dtNly0kUphwDtsFWDhF3PaZQIRCeI7RIXKhFMgrRFE6UL4AFFzhocQ1DAwaZElXFJaKjiCWWCY+acLCRz2AnriR08KMsEGN54nMtcGcWnUS2ewr/txLQDkipjADYmjoxsz+rDqp2IH+4y4ZFJf8=--jX6TlsuL0nwliAuN--lnbA1H3K7bwrmIjgJzAT9A==
\ No newline at end of file
diff --git a/config/database.yml b/config/database.yml
index 56d378d..843b079 100644
--- a/config/database.yml
+++ b/config/database.yml
@@ -11,8 +11,13 @@ default: &default
default_transaction_mode: IMMEDIATE
development:
- <<: *default
- database: storage/development.sqlite3
+ primary:
+ <<: *default
+ database: storage/development.sqlite3
+ queue:
+ <<: *default
+ database: storage/development_queue.sqlite3
+ migrations_paths: db/queue_migrate
# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
@@ -22,5 +27,10 @@ test:
database: storage/test.sqlite3
production:
- <<: *default
- database: storage/production.sqlite3
+ primary:
+ <<: *default
+ database: storage/production.sqlite3
+ queue:
+ <<: *default
+ database: storage/production_queue.sqlite3
+ migrations_paths: db/queue_migrate
diff --git a/config/environments/development.rb b/config/environments/development.rb
index c6145f2..a0f127e 100644
--- a/config/environments/development.rb
+++ b/config/environments/development.rb
@@ -60,6 +60,8 @@ Rails.application.configure do
# Highlight code that enqueued background job in logs.
config.active_job.verbose_enqueue_logs = true
+ config.active_job.queue_adapter = :solid_queue
+ config.solid_queue.connects_to = { database: { writing: :queue } }
# Suppress logger output for asset requests.
config.assets.quiet = true
@@ -67,7 +69,7 @@ Rails.application.configure do
# Raises error for missing translations.
# config.i18n.raise_on_missing_translations = true
- # Annotate rendered view with file names.
+ # Annotate rendered view with file nactive_jobames.
config.action_view.annotate_rendered_view_with_filenames = true
# Uncomment if you wish to allow Action Cable access from any origin.
diff --git a/config/environments/production.rb b/config/environments/production.rb
index b20131b..399551b 100644
--- a/config/environments/production.rb
+++ b/config/environments/production.rb
@@ -73,7 +73,9 @@ Rails.application.configure do
# config.cache_store = :mem_cache_store
# Use a real queuing backend for Active Job (and separate queues per environment).
- # config.active_job.queue_adapter = :resque
+ config.active_job.queue_adapter = :solid_queue
+ config.solid_queue.connects_to = { database: { writing: :queue } }
+
# config.active_job.queue_name_prefix = "a11yist_production"
# Disable caching for Action Mailer templates even if Action Controller
diff --git a/config/initializers/deepl.rb b/config/initializers/deepl.rb
new file mode 100644
index 0000000..007121a
--- /dev/null
+++ b/config/initializers/deepl.rb
@@ -0,0 +1,6 @@
+if Rails.application.credentials[:deepl_api_key]
+ DeepL.configure do |config|
+ config.auth_key = Rails.application.credentials[:deepl_api_key]
+ config.host = "https://api-free.deepl.com"
+ end
+end
diff --git a/config/initializers/prawn.rb b/config/initializers/prawn.rb
new file mode 100644
index 0000000..7754ea7
--- /dev/null
+++ b/config/initializers/prawn.rb
@@ -0,0 +1,9 @@
+PrawnRails.config do |config|
+ config.page_layout = :portrait
+ config.page_size = "A4"
+ config.skip_page_creation = false
+ config.left_margin = 32
+ config.top_margin = 64
+ config.right_margin = 32
+ config.bottom_margin = 32
+end
diff --git a/config/locales/activerecord.yml b/config/locales/activerecord.yml
index 2e7311a..7277847 100644
--- a/config/locales/activerecord.yml
+++ b/config/locales/activerecord.yml
@@ -14,7 +14,6 @@ de-CH:
quick_criterion: Quick Kriterium
quick_fail: Quick Fail
quick_fix: Quick Fix
- title: Titel
test_instructions: Testanleitung
check:
id: ID
@@ -92,9 +91,6 @@ de-CH:
check:
one: Check
other: Checks
- check:
- one: Check
- other: Checks
checklist_entry:
one: Zuweisung
other: Zuweisungen
@@ -122,3 +118,6 @@ de-CH:
page:
one: Pfad
other: Pfade
+ project:
+ one: Projekt
+ other: Projekte
diff --git a/config/puma.rb b/config/puma.rb
index 60e1b9c..5968b47 100644
--- a/config/puma.rb
+++ b/config/puma.rb
@@ -28,6 +28,7 @@ port ENV.fetch("PORT", 3000)
# Allow puma to be restarted by `bin/rails restart` command.
plugin :tmp_restart
+plugin :solid_queue
# Only use a pidfile when requested
pidfile ENV["PIDFILE"] if ENV["PIDFILE"]
diff --git a/config/queue.yml b/config/queue.yml
new file mode 100644
index 0000000..9eace59
--- /dev/null
+++ b/config/queue.yml
@@ -0,0 +1,18 @@
+default: &default
+ dispatchers:
+ - polling_interval: 1
+ batch_size: 500
+ workers:
+ - queues: "*"
+ threads: 3
+ processes: <%= ENV.fetch("JOB_CONCURRENCY", 1) %>
+ polling_interval: 0.1
+
+development:
+ <<: *default
+
+test:
+ <<: *default
+
+production:
+ <<: *default
diff --git a/config/recurring.yml b/config/recurring.yml
new file mode 100644
index 0000000..8486884
--- /dev/null
+++ b/config/recurring.yml
@@ -0,0 +1,10 @@
+# production:
+# cleanup_session:
+# class: CleanSoftDeletedRecordsJob
+# queue: background
+# args: [ 1000, { batch_size: 500 } ]
+# schedule: every hour
+# periodic_command:
+# command: "SoftDeletedRecord.due.delete_all"
+# priority: 2
+# schedule: at 5am every day
diff --git a/config/routes.rb b/config/routes.rb
index 9dcb17e..1c19c13 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -1,5 +1,6 @@
# Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html
Rails.application.routes.draw do
+ resources :guidelines
resource :session
resources :passwords, param: :token
namespace :admin do
@@ -11,20 +12,26 @@ Rails.application.routes.draw do
resources :checks
resources :link_categories
resources :links
- resources :reports, shallow: true, except: %i[show] do
- resources :pages do
- resources :elements do
- resources :success_criteria do
- collection do
- get "from_checklist", action: :new_from_checklist, as: :new_from_checklist
- post "from_checklist", action: :create_from_checklist, as: :create_from_checklist
+ resources :projects, shallow: true do
+ resources :reports, except: [:show] do
+ resources :pages do
+ resources :elements do
+ resources :success_criteria do
+ collection do
+ get "from_checklist", action: :new_from_checklist, as: :new_from_checklist
+ post "from_checklist", action: :create_from_checklist, as: :create_from_checklist
+ end
+
+ member do
+ get "edit_comment"
+ end
end
end
end
- end
- resource :export, only: %i[show]
- member do
- get "(-/:page_id)", action: :show, as: "", constraints: { id: /\d+/ }
+ resource :export, only: %i[show]
+ member do
+ get "(-/:page_id)", action: :show, as: "", constraints: { id: /\d+/ }
+ end
end
end
diff --git a/db/migrate/20241124183246_create_projects.rb b/db/migrate/20241124183246_create_projects.rb
new file mode 100644
index 0000000..b2dbe30
--- /dev/null
+++ b/db/migrate/20241124183246_create_projects.rb
@@ -0,0 +1,9 @@
+class CreateProjects < ActiveRecord::Migration[8.0]
+ def change
+ create_table :projects do |t|
+ t.string :name
+
+ t.timestamps
+ end
+ end
+end
diff --git a/db/migrate/20241124183406_add_project_to_reports.rb b/db/migrate/20241124183406_add_project_to_reports.rb
new file mode 100644
index 0000000..e840cdf
--- /dev/null
+++ b/db/migrate/20241124183406_add_project_to_reports.rb
@@ -0,0 +1,5 @@
+class AddProjectToReports < ActiveRecord::Migration[8.0]
+ def change
+ add_reference :reports, :project, null: true, foreign_key: true
+ end
+end
diff --git a/db/migrate/20250101163808_create_guidelines.rb b/db/migrate/20250101163808_create_guidelines.rb
new file mode 100644
index 0000000..197cb17
--- /dev/null
+++ b/db/migrate/20250101163808_create_guidelines.rb
@@ -0,0 +1,12 @@
+class CreateGuidelines < ActiveRecord::Migration[8.0]
+ def change
+ create_table :guidelines do |t|
+ t.references :principle, null: false, foreign_key: true
+ t.integer :number
+ t.string :name_de
+ t.string :name_en
+
+ t.timestamps
+ end
+ end
+end
diff --git a/db/migrate/20250101163835_add_guideline_id_to_checks.rb b/db/migrate/20250101163835_add_guideline_id_to_checks.rb
new file mode 100644
index 0000000..09662e8
--- /dev/null
+++ b/db/migrate/20250101163835_add_guideline_id_to_checks.rb
@@ -0,0 +1,6 @@
+class AddGuidelineIdToChecks < ActiveRecord::Migration[8.0]
+ def change
+ add_reference :checks, :guideline, null: false, foreign_key: true
+ remove_reference :checks, :principle
+ end
+end
diff --git a/db/migrate/20250101171836_remove_unique_number_constraint_on_checks.rb b/db/migrate/20250101171836_remove_unique_number_constraint_on_checks.rb
new file mode 100644
index 0000000..1406d2b
--- /dev/null
+++ b/db/migrate/20250101171836_remove_unique_number_constraint_on_checks.rb
@@ -0,0 +1,5 @@
+class RemoveUniqueNumberConstraintOnChecks < ActiveRecord::Migration[8.0]
+ def change
+ remove_index :checks, :number
+ end
+end
diff --git a/db/queue_schema.rb b/db/queue_schema.rb
new file mode 100644
index 0000000..4b2cdcd
--- /dev/null
+++ b/db/queue_schema.rb
@@ -0,0 +1,141 @@
+# This file is auto-generated from the current state of the database. Instead
+# of editing this file, please use the migrations feature of Active Record to
+# incrementally modify your database, and then regenerate this schema definition.
+#
+# This file is the source Rails uses to define your schema when running `bin/rails
+# db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to
+# be faster and is potentially less error prone than running all of your
+# migrations from scratch. Old migrations may fail to apply correctly if those
+# migrations use external dependencies or application code.
+#
+# It's strongly recommended that you check this file into your version control system.
+
+ActiveRecord::Schema[8.0].define(version: 1) do
+ create_table "solid_queue_blocked_executions", force: :cascade do |t|
+ t.bigint "job_id", null: false
+ t.string "queue_name", null: false
+ t.integer "priority", default: 0, null: false
+ t.string "concurrency_key", null: false
+ t.datetime "expires_at", null: false
+ t.datetime "created_at", null: false
+ t.index ["concurrency_key", "priority", "job_id"], name: "index_solid_queue_blocked_executions_for_release"
+ t.index ["expires_at", "concurrency_key"], name: "index_solid_queue_blocked_executions_for_maintenance"
+ t.index ["job_id"], name: "index_solid_queue_blocked_executions_on_job_id", unique: true
+ end
+
+ create_table "solid_queue_claimed_executions", force: :cascade do |t|
+ t.bigint "job_id", null: false
+ t.bigint "process_id"
+ t.datetime "created_at", null: false
+ t.index ["job_id"], name: "index_solid_queue_claimed_executions_on_job_id", unique: true
+ t.index ["process_id", "job_id"], name: "index_solid_queue_claimed_executions_on_process_id_and_job_id"
+ end
+
+ create_table "solid_queue_failed_executions", force: :cascade do |t|
+ t.bigint "job_id", null: false
+ t.text "error"
+ t.datetime "created_at", null: false
+ t.index ["job_id"], name: "index_solid_queue_failed_executions_on_job_id", unique: true
+ end
+
+ create_table "solid_queue_jobs", force: :cascade do |t|
+ t.string "queue_name", null: false
+ t.string "class_name", null: false
+ t.text "arguments"
+ t.integer "priority", default: 0, null: false
+ t.string "active_job_id"
+ t.datetime "scheduled_at"
+ t.datetime "finished_at"
+ t.string "concurrency_key"
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
+ t.index ["active_job_id"], name: "index_solid_queue_jobs_on_active_job_id"
+ t.index ["class_name"], name: "index_solid_queue_jobs_on_class_name"
+ t.index ["finished_at"], name: "index_solid_queue_jobs_on_finished_at"
+ t.index ["queue_name", "finished_at"], name: "index_solid_queue_jobs_for_filtering"
+ t.index ["scheduled_at", "finished_at"], name: "index_solid_queue_jobs_for_alerting"
+ end
+
+ create_table "solid_queue_pauses", force: :cascade do |t|
+ t.string "queue_name", null: false
+ t.datetime "created_at", null: false
+ t.index ["queue_name"], name: "index_solid_queue_pauses_on_queue_name", unique: true
+ end
+
+ create_table "solid_queue_processes", force: :cascade do |t|
+ t.string "kind", null: false
+ t.datetime "last_heartbeat_at", null: false
+ t.bigint "supervisor_id"
+ t.integer "pid", null: false
+ t.string "hostname"
+ t.text "metadata"
+ t.datetime "created_at", null: false
+ t.string "name", null: false
+ t.index ["last_heartbeat_at"], name: "index_solid_queue_processes_on_last_heartbeat_at"
+ t.index ["name", "supervisor_id"], name: "index_solid_queue_processes_on_name_and_supervisor_id", unique: true
+ t.index ["supervisor_id"], name: "index_solid_queue_processes_on_supervisor_id"
+ end
+
+ create_table "solid_queue_ready_executions", force: :cascade do |t|
+ t.bigint "job_id", null: false
+ t.string "queue_name", null: false
+ t.integer "priority", default: 0, null: false
+ t.datetime "created_at", null: false
+ t.index ["job_id"], name: "index_solid_queue_ready_executions_on_job_id", unique: true
+ t.index ["priority", "job_id"], name: "index_solid_queue_poll_all"
+ t.index ["queue_name", "priority", "job_id"], name: "index_solid_queue_poll_by_queue"
+ end
+
+ create_table "solid_queue_recurring_executions", force: :cascade do |t|
+ t.bigint "job_id", null: false
+ t.string "task_key", null: false
+ t.datetime "run_at", null: false
+ t.datetime "created_at", null: false
+ t.index ["job_id"], name: "index_solid_queue_recurring_executions_on_job_id", unique: true
+ t.index ["task_key", "run_at"], name: "index_solid_queue_recurring_executions_on_task_key_and_run_at", unique: true
+ end
+
+ create_table "solid_queue_recurring_tasks", force: :cascade do |t|
+ t.string "key", null: false
+ t.string "schedule", null: false
+ t.string "command", limit: 2048
+ t.string "class_name"
+ t.text "arguments"
+ t.string "queue_name"
+ t.integer "priority", default: 0
+ t.boolean "static", default: true, null: false
+ t.text "description"
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
+ t.index ["key"], name: "index_solid_queue_recurring_tasks_on_key", unique: true
+ t.index ["static"], name: "index_solid_queue_recurring_tasks_on_static"
+ end
+
+ create_table "solid_queue_scheduled_executions", force: :cascade do |t|
+ t.bigint "job_id", null: false
+ t.string "queue_name", null: false
+ t.integer "priority", default: 0, null: false
+ t.datetime "scheduled_at", null: false
+ t.datetime "created_at", null: false
+ t.index ["job_id"], name: "index_solid_queue_scheduled_executions_on_job_id", unique: true
+ t.index ["scheduled_at", "priority", "job_id"], name: "index_solid_queue_dispatch_all"
+ end
+
+ create_table "solid_queue_semaphores", force: :cascade do |t|
+ t.string "key", null: false
+ t.integer "value", default: 1, null: false
+ t.datetime "expires_at", null: false
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
+ t.index ["expires_at"], name: "index_solid_queue_semaphores_on_expires_at"
+ t.index ["key", "value"], name: "index_solid_queue_semaphores_on_key_and_value"
+ t.index ["key"], name: "index_solid_queue_semaphores_on_key", unique: true
+ end
+
+ add_foreign_key "solid_queue_blocked_executions", "solid_queue_jobs", column: "job_id", on_delete: :cascade
+ add_foreign_key "solid_queue_claimed_executions", "solid_queue_jobs", column: "job_id", on_delete: :cascade
+ add_foreign_key "solid_queue_failed_executions", "solid_queue_jobs", column: "job_id", on_delete: :cascade
+ add_foreign_key "solid_queue_ready_executions", "solid_queue_jobs", column: "job_id", on_delete: :cascade
+ add_foreign_key "solid_queue_recurring_executions", "solid_queue_jobs", column: "job_id", on_delete: :cascade
+ add_foreign_key "solid_queue_scheduled_executions", "solid_queue_jobs", column: "job_id", on_delete: :cascade
+end
diff --git a/db/schema.rb b/db/schema.rb
index 7623c6e..55b94e9 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,19 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema[8.0].define(version: 2024_11_11_034826) do
+ActiveRecord::Schema[8.0].define(version: 2025_01_01_171836) do
+ create_table "account_remember_keys", force: :cascade do |t|
+ t.string "key", null: false
+ t.datetime "deadline", null: false
+ end
+
+ create_table "accounts", force: :cascade do |t|
+ t.integer "status", default: 1, null: false
+ t.string "email", null: false
+ t.string "password_hash"
+ t.index ["email"], name: "index_accounts_on_email", unique: true, where: "status IN (1, 2)"
+ end
+
create_table "action_text_rich_texts", force: :cascade do |t|
t.string "name", null: false
t.text "body"
@@ -82,7 +94,6 @@ ActiveRecord::Schema[8.0].define(version: 2024_11_11_034826) do
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.integer "conformity_level"
t.integer "priority"
t.boolean "manual_test", default: true, null: false
@@ -94,8 +105,8 @@ ActiveRecord::Schema[8.0].define(version: 2024_11_11_034826) do
t.integer "external_number_1"
t.integer "external_number_2"
t.integer "external_number_3"
- t.index ["number"], name: "index_checks_on_number", unique: true
- t.index ["principle_id"], name: "index_checks_on_principle_id"
+ t.integer "guideline_id", null: false
+ t.index ["guideline_id"], name: "index_checks_on_guideline_id"
end
create_table "checks_links", id: false, force: :cascade do |t|
@@ -115,9 +126,20 @@ ActiveRecord::Schema[8.0].define(version: 2024_11_11_034826) do
t.datetime "updated_at", null: false
t.integer "page_id", null: false
t.integer "position", null: false
+ t.index ["page_id", "position"], name: "index_elements_on_page_id_and_position", unique: true
t.index ["page_id"], name: "index_elements_on_page_id"
end
+ create_table "guidelines", force: :cascade do |t|
+ t.integer "principle_id", null: false
+ t.integer "number"
+ t.string "name_de"
+ t.string "name_en"
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
+ t.index ["principle_id"], name: "index_guidelines_on_principle_id"
+ end
+
create_table "link_categories", force: :cascade do |t|
t.string "name"
t.text "description"
@@ -144,6 +166,7 @@ ActiveRecord::Schema[8.0].define(version: 2024_11_11_034826) do
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.text "notes"
+ t.index ["report_id", "position"], name: "index_pages_on_report_id_and_position", unique: true
t.index ["report_id"], name: "index_pages_on_report_id"
end
@@ -154,11 +177,19 @@ ActiveRecord::Schema[8.0].define(version: 2024_11_11_034826) do
t.datetime "updated_at", null: false
end
+ create_table "projects", force: :cascade do |t|
+ t.string "name"
+ 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
t.string "url"
+ t.integer "project_id"
+ t.index ["project_id"], name: "index_reports_on_project_id"
end
create_table "sessions", force: :cascade do |t|
@@ -191,6 +222,7 @@ ActiveRecord::Schema[8.0].define(version: 2024_11_11_034826) do
t.integer "priority"
t.integer "position", null: false
t.index ["check_id"], name: "index_success_criteria_on_check_id"
+ t.index ["element_id", "position"], name: "index_success_criteria_on_element_id_and_position", unique: true
t.index ["element_id"], name: "index_success_criteria_on_element_id"
end
@@ -202,14 +234,17 @@ ActiveRecord::Schema[8.0].define(version: 2024_11_11_034826) do
t.index ["email_address"], name: "index_users_on_email_address", unique: true
end
+ add_foreign_key "account_remember_keys", "accounts", column: "id"
add_foreign_key "active_storage_attachments", "active_storage_blobs", column: "blob_id"
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 "checks", "guidelines"
add_foreign_key "elements", "pages"
+ add_foreign_key "guidelines", "principles"
add_foreign_key "links", "link_categories"
add_foreign_key "pages", "reports"
+ add_foreign_key "reports", "projects"
add_foreign_key "sessions", "users"
add_foreign_key "success_criteria", "checks"
add_foreign_key "success_criteria", "elements"
diff --git a/db/seeds.rb b/db/seeds.rb
index b0ddeb2..bf0bfc7 100644
--- a/db/seeds.rb
+++ b/db/seeds.rb
@@ -72,6 +72,8 @@ Principle.create!(name_de: "Verständlich", name_en: "Understandable")
Principle.create!(name_de: "Robust", name_en: "Robust")
Principle.create!(name_de: "Sonstige", name_en: "Other")
+LinkCategory.create!(name: "Verstehen")
+LinkCategory.create!(name: "WCAG Quick Reference")
LinkCategory.create!(name: "Tools")
LinkCategory.create!(name: "Beispiele")
LinkCategory.create!(name: "Artikel")
@@ -92,4 +94,3 @@ Link.create!(url: "https://www.a11yproject.com/",
link_category: LinkCategory.find_by(name: "Artikel"))
User.find_or_initialize_by(email_address: "admin@example.com").update!(password: "password")
-User.find_or_initialize_by(email_address: "goran@quiet.ch").update!(password: "password")
\ No newline at end of file
diff --git a/docker-compose.yml b/docker-compose.yml
deleted file mode 100644
index dc06931..0000000
--- a/docker-compose.yml
+++ /dev/null
@@ -1,50 +0,0 @@
-# This is available in $COMPOSE_PROJECT_NAME
-name: a11yist
-
-networks:
- traefik:
- external: true
-
-services:
- app: &app
- build:
- context: .
- target: development
- volumes:
- - ./:/app:cached
- - ${PWD}:${PWD}
- - ${HOME}/.tabby-client:/home/app/.tabby-client
- - ${SSH_AUTH_SOCK}:/ssh-agent
- env_file:
- - .env
- environment:
- RAILS_ENV: development
- LOG_LEVEL: debug
- TRUSTED_IP: 172.16.0.0/12,192.168.0.0/16,10.0.0.0/24
- SSH_AUTH_SOCK: /ssh-agent
- RAILS_SERVE_STATIC_FILES: 1
- APP_HOST: ${COMPOSE_PROJECT_NAME}.localhost
- HISTFILE: /app/tmp/.bash_history
- PSQL_HISTORY: /app/tmp/.psql_history
- IRBRC: /app/.irbrc
- SELENIUM_REMOTE_URL: http://chrome:4444/wd/hub
- labels:
- - traefik.http.routers.app-${COMPOSE_PROJECT_NAME}.entrypoints=http
- - traefik.http.routers.app-${COMPOSE_PROJECT_NAME}.rule=Host(`${COMPOSE_PROJECT_NAME}.localhost`)
- - traefik.http.services.app-${COMPOSE_PROJECT_NAME}.loadbalancer.server.port=3000
- - traefik.docker.network=traefik
- networks:
- - traefik
- - default
-
- chrome:
- image: selenium/standalone-chrome
- shm_size: 2g
- labels:
- - traefik.http.routers.chrome-${COMPOSE_PROJECT_NAME}.entrypoints=http
- - traefik.http.routers.chrome-${COMPOSE_PROJECT_NAME}.rule=Host(`chrome.${COMPOSE_PROJECT_NAME}.localhost`)
- - traefik.http.services.chrome-${COMPOSE_PROJECT_NAME}.loadbalancer.server.port=4444
- - traefik.docker.network=traefik
- networks:
- - traefik
- - default
diff --git a/lib/tasks/import.rake b/lib/tasks/import.rake
index dccb8d4..ef0cc5a 100644
--- a/lib/tasks/import.rake
+++ b/lib/tasks/import.rake
@@ -1,20 +1,66 @@
# frozen_string_literal: true
+
URL = "https://outline-rocks.github.io/wcag/translations/WCAG21-de/"
WCAG_22_EN_URL ="https://www.w3.org/TR/WCAG22/"
+WCAG_22_EN_QREF_URL = "https://www.w3.org/WAI/WCAG22/quickref/"
+
+def translate(input)
+ DeepL.translate(input, "EN", "DE")
+end
def import_wcag22en
doc = Nokogiri::HTML5(URI.open(WCAG_22_EN_URL))
- standards = [Standard.find_by(name_de: "WCAG 2.2"), Standard.find_by(name_de: "EN 301 549")]
+ qrefdoc = Nokogiri::HTML5(URI.open(WCAG_22_EN_QREF_URL))
+ quick_criteria = qrefdoc.css(".guidelines section:has(h4)").each_with_object({}) do |node, h|
+ h[node.css("h4 strong").first.content] = {
+ quick_criterion_en: node.css(".sc-content .sc-text p").first.content,
+ link_url: node.css(".understanding a").first.attribute("href").value,
+ perm_url: "#{WCAG_22_EN_QREF_URL}##{node.css("article").first.attribute("id").value}"
+ }
+ rescue
+ debugger
+ end
+ link_category = LinkCategory.find_by(name: "Verstehen")
+ qr_category = LinkCategory.find_by(name: "WCAG Quick Reference")
+ # debugger
+ # raise ActiveRecord::Rollback
+
+ standards = [ Standard.find_by(name_de: "WCAG 2.2"), Standard.find_by(name_de: "EN 301 549") ]
doc.css("section.principle").each do |principle_node|
_principle_id = principle_node.attributes["id"].value
principle_title = principle_node.css("h2").first.content.scan(/([a-zA-Z]+)/)
- principle = Principle.find_by!(name_en: principle_title)
+ principle = Principle.find_or_create_by!(name_en: principle_title)
+
principle_node.css("section.guideline").each do |guideline_node|
+ next unless guideline_node.css("h3").first
+
+ puts guideline_node.css("h3").first&.content
+ puts guideline_node.css_path
+
+ g_title = guideline_node.css("h3")
+ .first
+ .content
+ .scan(/Guideline \d+\.\d+ (.*)/)
+ .first
+ .first
+ g_number = guideline_node.css("h3 bdi")
+ .first
+ .content
+ .scan(/\d+\.(\d+)/)
+ .first
+ .first
+ g_text = guideline_node.css("> p").first.content
+
+ guideline = Guideline.find_or_create_by(principle: principle, number: g_number, name_en: g_title)
+ guideline.update(description_en: g_text, description_de: translate(g_text), name_de: translate(g_title)) if guideline.description_de.blank?
+
guideline_node.css("section.guideline").each do |sc|
+ puts sc.css_path
+ puts sc.css("h4 bdi")
sc_number, sc_title = sc.css("h4")
.first
.content
- .scan(/Success Criterion (\d+\.\d+\.\d+) (.*)/)
+ .scan(/Success Criterion \d+\.\d+\.(\d+) (.*)/)
.first
sc_level = sc.css("p.conformance-level").first&.content&.scan(/\(Level (A+)\)/)&.first&.last
sc_url = sc.css("a.self-link").first.attr("href")
@@ -23,20 +69,35 @@ def import_wcag22en
.select { _1.class == Nokogiri::XML::Element }
.select { _1.attr("class").nil? || _1.attr("class") == "note" }
.reduce("") { |str, node| str + node.to_s }
-
- check = Check.find_or_initialize_by(external_number: sc_number)
+
+ check = Check.find_or_initialize_by(guideline_id: guideline.id, number: sc_number)
new_standards = Set.new(check.standards)
new_standards += standards
- check.name_de = sc_title
+ check.name_de = translate sc_title if check.name_de.blank?
check.name_en = sc_title
- check.principle = principle
check.standards = new_standards
check.applicable_to_app = check.applicable_to_web = true
- check.external_number = sc_number
check.external_url = "#{WCAG_22_EN_URL}#{sc_url}"
check.conformity_level = sc_level&.to_sym
- check.conformity_notice_de = sc_conformity_notice
- check.criterion_de = "#{full_text}
".gsub('href="#', %(href="#{WCAG_22_EN_URL}#))
+ check.conformity_notice_de = translate sc_conformity_notice
+ check.criterion_de = "#{translate full_text}
".gsub('href="#', %(href="#{WCAG_22_EN_URL}#)) if check.criterion_de.blank?
+ qref_attrs = quick_criteria["#{principle.id}.#{guideline.number}.#{sc_number}"]
+ check.quick_criterion_en = qref_attrs&.dig :quick_criterion_en
+ check.quick_criterion_de = qref_attrs&.dig :quick_criterion_en
+
+ if qref_attrs&.dig(:link_url)
+ link = Link.find_or_create_by(link_category:, url: qref_attrs[:link_url])
+ link.update(text: "#{check.full_number} Verstehen")
+ check.links << link
+ end
+
+ if qref_attrs&.dig(:perm_url)
+ link = Link.find_or_create_by(link_category: qr_category, url: qref_attrs[:perm_url])
+ link.update(text: "#{check.full_number} Quick Reference")
+ check.links << link
+ end
+ # check.criterion_details_en = qref_attrs&.dig :criterion_details_en
+ # check.criterion_details_de = qref_attrs&.dig :criterion_details_en
check.save!
end
end
diff --git a/package-lock.json b/package-lock.json
deleted file mode 100644
index a189879..0000000
--- a/package-lock.json
+++ /dev/null
@@ -1,1378 +0,0 @@
-{
- "name": "app",
- "lockfileVersion": 3,
- "requires": true,
- "packages": {
- "": {
- "name": "app",
- "dependencies": {
- "@hotwired/stimulus": "^3.2.2",
- "@hotwired/turbo-rails": "^8.0.4",
- "@popperjs/core": "^2.11.8",
- "@rails/actiontext": "^7.1.3-4",
- "autoprefixer": "^10.4.19",
- "bootstrap": "^5.3.3",
- "bootstrap-icons": "^1.11.3",
- "esbuild": "^0.23.0",
- "nodemon": "^3.1.4",
- "postcss": "^8.4.39",
- "postcss-cli": "^11.0.0",
- "sass": "^1.77.8",
- "trix": "^2.1.3"
- },
- "devDependencies": {
- "tabby-agent": "^1.7.0"
- }
- },
- "node_modules/@esbuild/linux-x64": {
- "version": "0.23.0",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.23.0.tgz",
- "integrity": "sha512-a3pMQhUEJkITgAw6e0bWA+F+vFtCciMjW/LPtoj99MhVt+Mfb6bbL9hu2wmTZgNd994qTAEw+U/r6k3qHWWaOQ==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@hotwired/stimulus": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/@hotwired/stimulus/-/stimulus-3.2.2.tgz",
- "integrity": "sha512-eGeIqNOQpXoPAIP7tC1+1Yc1yl1xnwYqg+3mzqxyrbE5pg5YFBZcA6YoTiByJB6DKAEsiWtl6tjTJS4IYtbB7A==",
- "license": "MIT"
- },
- "node_modules/@hotwired/turbo": {
- "version": "8.0.4",
- "resolved": "https://registry.npmjs.org/@hotwired/turbo/-/turbo-8.0.4.tgz",
- "integrity": "sha512-mlZEFUZrJnpfj+g/XeCWWuokvQyN68WvM78JM+0jfSFc98wegm259vCbC1zSllcspRwbgXK31ibehCy5PA78/Q==",
- "license": "MIT",
- "engines": {
- "node": ">= 14"
- }
- },
- "node_modules/@hotwired/turbo-rails": {
- "version": "8.0.4",
- "resolved": "https://registry.npmjs.org/@hotwired/turbo-rails/-/turbo-rails-8.0.4.tgz",
- "integrity": "sha512-GHCv5+B2VzYZZvMFpg/g9JLx/8pl/8chcubSB7T+Xn1zYOMqAKB6cT80vvWUzxdwfm/2KfaRysfDz+BmvtjFaw==",
- "license": "MIT",
- "dependencies": {
- "@hotwired/turbo": "^8.0.4",
- "@rails/actioncable": "^7.0"
- }
- },
- "node_modules/@nodelib/fs.scandir": {
- "version": "2.1.5",
- "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
- "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
- "license": "MIT",
- "dependencies": {
- "@nodelib/fs.stat": "2.0.5",
- "run-parallel": "^1.1.9"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/@nodelib/fs.stat": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
- "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
- "license": "MIT",
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/@nodelib/fs.walk": {
- "version": "1.2.8",
- "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
- "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
- "license": "MIT",
- "dependencies": {
- "@nodelib/fs.scandir": "2.1.5",
- "fastq": "^1.6.0"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/@popperjs/core": {
- "version": "2.11.8",
- "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz",
- "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==",
- "license": "MIT",
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/popperjs"
- }
- },
- "node_modules/@rails/actioncable": {
- "version": "7.1.3",
- "resolved": "https://registry.npmjs.org/@rails/actioncable/-/actioncable-7.1.3.tgz",
- "integrity": "sha512-ojNvnoZtPN0pYvVFtlO7dyEN9Oml1B6IDM+whGKVak69MMYW99lC2NOWXWeE3bmwEydbP/nn6ERcpfjHVjYQjA==",
- "license": "MIT"
- },
- "node_modules/@rails/actiontext": {
- "version": "7.1.3-4",
- "resolved": "https://registry.npmjs.org/@rails/actiontext/-/actiontext-7.1.3-4.tgz",
- "integrity": "sha512-Yt0aFwV4vmQDH0SPMKACF5WnZ88vn8KHpCbPJIGnFcj4likev+SkmdCLu/TpcHrFQwHWXt+GwKE924Ny92YXAg==",
- "license": "MIT",
- "dependencies": {
- "@rails/activestorage": ">= 7.1.0-alpha"
- },
- "peerDependencies": {
- "trix": "^2.0.0"
- }
- },
- "node_modules/@rails/activestorage": {
- "version": "7.1.3",
- "resolved": "https://registry.npmjs.org/@rails/activestorage/-/activestorage-7.1.3.tgz",
- "integrity": "sha512-B+RFYAU8vdTPFg0IJcRp2ey0Qw9hpcUOqHHcWqftDJ76ZMBi9+m/UUeMJlNsSd0l9eD+1HLlFSo1X//cY4yiDw==",
- "license": "MIT",
- "dependencies": {
- "spark-md5": "^3.0.1"
- }
- },
- "node_modules/@sindresorhus/merge-streams": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz",
- "integrity": "sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==",
- "license": "MIT",
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/ansi-regex": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
- "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/ansi-styles": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
- "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
- "license": "MIT",
- "dependencies": {
- "color-convert": "^2.0.1"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-styles?sponsor=1"
- }
- },
- "node_modules/anymatch": {
- "version": "3.1.3",
- "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
- "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
- "license": "ISC",
- "dependencies": {
- "normalize-path": "^3.0.0",
- "picomatch": "^2.0.4"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/autoprefixer": {
- "version": "10.4.19",
- "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.19.tgz",
- "integrity": "sha512-BaENR2+zBZ8xXhM4pUaKUxlVdxZ0EZhjvbopwnXmxRUfqDmwSpC2lAi/QXvx7NRdPCo1WKEcEF6mV64si1z4Ew==",
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/postcss/"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/autoprefixer"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "license": "MIT",
- "dependencies": {
- "browserslist": "^4.23.0",
- "caniuse-lite": "^1.0.30001599",
- "fraction.js": "^4.3.7",
- "normalize-range": "^0.1.2",
- "picocolors": "^1.0.0",
- "postcss-value-parser": "^4.2.0"
- },
- "bin": {
- "autoprefixer": "bin/autoprefixer"
- },
- "engines": {
- "node": "^10 || ^12 || >=14"
- },
- "peerDependencies": {
- "postcss": "^8.1.0"
- }
- },
- "node_modules/balanced-match": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
- "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
- "license": "MIT"
- },
- "node_modules/binary-extensions": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
- "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==",
- "license": "MIT",
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/bootstrap": {
- "version": "5.3.3",
- "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.3.tgz",
- "integrity": "sha512-8HLCdWgyoMguSO9o+aH+iuZ+aht+mzW0u3HIMzVu7Srrpv7EBBxTnrFlSCskwdY1+EOFQSm7uMJhNQHkdPcmjg==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/twbs"
- },
- {
- "type": "opencollective",
- "url": "https://opencollective.com/bootstrap"
- }
- ],
- "license": "MIT",
- "peerDependencies": {
- "@popperjs/core": "^2.11.8"
- }
- },
- "node_modules/bootstrap-icons": {
- "version": "1.11.3",
- "resolved": "https://registry.npmjs.org/bootstrap-icons/-/bootstrap-icons-1.11.3.tgz",
- "integrity": "sha512-+3lpHrCw/it2/7lBL15VR0HEumaBss0+f/Lb6ZvHISn1mlK83jjFpooTLsMWbIjJMDjDjOExMsTxnXSIT4k4ww==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/twbs"
- },
- {
- "type": "opencollective",
- "url": "https://opencollective.com/bootstrap"
- }
- ],
- "license": "MIT"
- },
- "node_modules/brace-expansion": {
- "version": "1.1.11",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
- "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
- "license": "MIT",
- "dependencies": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
- }
- },
- "node_modules/braces": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
- "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
- "license": "MIT",
- "dependencies": {
- "fill-range": "^7.1.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/browserslist": {
- "version": "4.23.2",
- "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.2.tgz",
- "integrity": "sha512-qkqSyistMYdxAcw+CzbZwlBy8AGmS/eEWs+sEV5TnLRGDOL+C5M2EnH6tlZyg0YoAxGJAFKh61En9BR941GnHA==",
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/browserslist"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/browserslist"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "license": "MIT",
- "dependencies": {
- "caniuse-lite": "^1.0.30001640",
- "electron-to-chromium": "^1.4.820",
- "node-releases": "^2.0.14",
- "update-browserslist-db": "^1.1.0"
- },
- "bin": {
- "browserslist": "cli.js"
- },
- "engines": {
- "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
- }
- },
- "node_modules/caniuse-lite": {
- "version": "1.0.30001642",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001642.tgz",
- "integrity": "sha512-3XQ0DoRgLijXJErLSl+bLnJ+Et4KqV1PY6JJBGAFlsNsz31zeAIncyeZfLCabHK/jtSh+671RM9YMldxjUPZtA==",
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/browserslist"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "license": "CC-BY-4.0"
- },
- "node_modules/chokidar": {
- "version": "3.6.0",
- "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
- "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
- "license": "MIT",
- "dependencies": {
- "anymatch": "~3.1.2",
- "braces": "~3.0.2",
- "glob-parent": "~5.1.2",
- "is-binary-path": "~2.1.0",
- "is-glob": "~4.0.1",
- "normalize-path": "~3.0.0",
- "readdirp": "~3.6.0"
- },
- "engines": {
- "node": ">= 8.10.0"
- },
- "funding": {
- "url": "https://paulmillr.com/funding/"
- },
- "optionalDependencies": {
- "fsevents": "~2.3.2"
- }
- },
- "node_modules/cliui": {
- "version": "8.0.1",
- "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
- "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
- "license": "ISC",
- "dependencies": {
- "string-width": "^4.2.0",
- "strip-ansi": "^6.0.1",
- "wrap-ansi": "^7.0.0"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/color-convert": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
- "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
- "license": "MIT",
- "dependencies": {
- "color-name": "~1.1.4"
- },
- "engines": {
- "node": ">=7.0.0"
- }
- },
- "node_modules/color-name": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
- "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
- "license": "MIT"
- },
- "node_modules/concat-map": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
- "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
- "license": "MIT"
- },
- "node_modules/debug": {
- "version": "4.3.5",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz",
- "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==",
- "license": "MIT",
- "dependencies": {
- "ms": "2.1.2"
- },
- "engines": {
- "node": ">=6.0"
- },
- "peerDependenciesMeta": {
- "supports-color": {
- "optional": true
- }
- }
- },
- "node_modules/dependency-graph": {
- "version": "0.11.0",
- "resolved": "https://registry.npmjs.org/dependency-graph/-/dependency-graph-0.11.0.tgz",
- "integrity": "sha512-JeMq7fEshyepOWDfcfHK06N3MhyPhz++vtqWhMT5O9A3K42rdsEDpfdVqjaqaAhsw6a+ZqeDvQVtD0hFHQWrzg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6.0"
- }
- },
- "node_modules/electron-to-chromium": {
- "version": "1.4.827",
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.827.tgz",
- "integrity": "sha512-VY+J0e4SFcNfQy19MEoMdaIcZLmDCprqvBtkii1WTCTQHpRvf5N8+3kTYCgL/PcntvwQvmMJWTuDPsq+IlhWKQ==",
- "license": "ISC"
- },
- "node_modules/emoji-regex": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
- "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
- "license": "MIT"
- },
- "node_modules/esbuild": {
- "version": "0.23.0",
- "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.23.0.tgz",
- "integrity": "sha512-1lvV17H2bMYda/WaFb2jLPeHU3zml2k4/yagNMG8Q/YtfMjCwEUZa2eXXMgZTVSL5q1n4H7sQ0X6CdJDqqeCFA==",
- "hasInstallScript": true,
- "license": "MIT",
- "bin": {
- "esbuild": "bin/esbuild"
- },
- "engines": {
- "node": ">=18"
- },
- "optionalDependencies": {
- "@esbuild/aix-ppc64": "0.23.0",
- "@esbuild/android-arm": "0.23.0",
- "@esbuild/android-arm64": "0.23.0",
- "@esbuild/android-x64": "0.23.0",
- "@esbuild/darwin-arm64": "0.23.0",
- "@esbuild/darwin-x64": "0.23.0",
- "@esbuild/freebsd-arm64": "0.23.0",
- "@esbuild/freebsd-x64": "0.23.0",
- "@esbuild/linux-arm": "0.23.0",
- "@esbuild/linux-arm64": "0.23.0",
- "@esbuild/linux-ia32": "0.23.0",
- "@esbuild/linux-loong64": "0.23.0",
- "@esbuild/linux-mips64el": "0.23.0",
- "@esbuild/linux-ppc64": "0.23.0",
- "@esbuild/linux-riscv64": "0.23.0",
- "@esbuild/linux-s390x": "0.23.0",
- "@esbuild/linux-x64": "0.23.0",
- "@esbuild/netbsd-x64": "0.23.0",
- "@esbuild/openbsd-arm64": "0.23.0",
- "@esbuild/openbsd-x64": "0.23.0",
- "@esbuild/sunos-x64": "0.23.0",
- "@esbuild/win32-arm64": "0.23.0",
- "@esbuild/win32-ia32": "0.23.0",
- "@esbuild/win32-x64": "0.23.0"
- }
- },
- "node_modules/escalade": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz",
- "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==",
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/fast-glob": {
- "version": "3.3.2",
- "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz",
- "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==",
- "license": "MIT",
- "dependencies": {
- "@nodelib/fs.stat": "^2.0.2",
- "@nodelib/fs.walk": "^1.2.3",
- "glob-parent": "^5.1.2",
- "merge2": "^1.3.0",
- "micromatch": "^4.0.4"
- },
- "engines": {
- "node": ">=8.6.0"
- }
- },
- "node_modules/fastq": {
- "version": "1.17.1",
- "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz",
- "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==",
- "license": "ISC",
- "dependencies": {
- "reusify": "^1.0.4"
- }
- },
- "node_modules/fill-range": {
- "version": "7.1.1",
- "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
- "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
- "license": "MIT",
- "dependencies": {
- "to-regex-range": "^5.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/fraction.js": {
- "version": "4.3.7",
- "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz",
- "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==",
- "license": "MIT",
- "engines": {
- "node": "*"
- },
- "funding": {
- "type": "patreon",
- "url": "https://github.com/sponsors/rawify"
- }
- },
- "node_modules/fs-extra": {
- "version": "11.2.0",
- "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz",
- "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==",
- "license": "MIT",
- "dependencies": {
- "graceful-fs": "^4.2.0",
- "jsonfile": "^6.0.1",
- "universalify": "^2.0.0"
- },
- "engines": {
- "node": ">=14.14"
- }
- },
- "node_modules/get-caller-file": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
- "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
- "license": "ISC",
- "engines": {
- "node": "6.* || 8.* || >= 10.*"
- }
- },
- "node_modules/get-stdin": {
- "version": "9.0.0",
- "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-9.0.0.tgz",
- "integrity": "sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==",
- "license": "MIT",
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/glob-parent": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
- "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
- "license": "ISC",
- "dependencies": {
- "is-glob": "^4.0.1"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/globby": {
- "version": "14.0.2",
- "resolved": "https://registry.npmjs.org/globby/-/globby-14.0.2.tgz",
- "integrity": "sha512-s3Fq41ZVh7vbbe2PN3nrW7yC7U7MFVc5c98/iTl9c2GawNMKx/J648KQRW6WKkuU8GIbbh2IXfIRQjOZnXcTnw==",
- "license": "MIT",
- "dependencies": {
- "@sindresorhus/merge-streams": "^2.1.0",
- "fast-glob": "^3.3.2",
- "ignore": "^5.2.4",
- "path-type": "^5.0.0",
- "slash": "^5.1.0",
- "unicorn-magic": "^0.1.0"
- },
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/graceful-fs": {
- "version": "4.2.11",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
- "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
- "license": "ISC"
- },
- "node_modules/has-flag": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
- "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
- "license": "MIT",
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/ignore": {
- "version": "5.3.1",
- "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz",
- "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==",
- "license": "MIT",
- "engines": {
- "node": ">= 4"
- }
- },
- "node_modules/ignore-by-default": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz",
- "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==",
- "license": "ISC"
- },
- "node_modules/immutable": {
- "version": "4.3.6",
- "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.6.tgz",
- "integrity": "sha512-Ju0+lEMyzMVZarkTn/gqRpdqd5dOPaz1mCZ0SH3JV6iFw81PldE/PEB1hWVEA288HPt4WXW8O7AWxB10M+03QQ==",
- "license": "MIT"
- },
- "node_modules/is-binary-path": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
- "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
- "license": "MIT",
- "dependencies": {
- "binary-extensions": "^2.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/is-extglob": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
- "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/is-fullwidth-code-point": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
- "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/is-glob": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
- "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
- "license": "MIT",
- "dependencies": {
- "is-extglob": "^2.1.1"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/is-number": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
- "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
- "license": "MIT",
- "engines": {
- "node": ">=0.12.0"
- }
- },
- "node_modules/jsonfile": {
- "version": "6.1.0",
- "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
- "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
- "license": "MIT",
- "dependencies": {
- "universalify": "^2.0.0"
- },
- "optionalDependencies": {
- "graceful-fs": "^4.1.6"
- }
- },
- "node_modules/lilconfig": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz",
- "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==",
- "license": "MIT",
- "engines": {
- "node": ">=14"
- },
- "funding": {
- "url": "https://github.com/sponsors/antonk52"
- }
- },
- "node_modules/merge2": {
- "version": "1.4.1",
- "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
- "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
- "license": "MIT",
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/micromatch": {
- "version": "4.0.7",
- "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz",
- "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==",
- "license": "MIT",
- "dependencies": {
- "braces": "^3.0.3",
- "picomatch": "^2.3.1"
- },
- "engines": {
- "node": ">=8.6"
- }
- },
- "node_modules/minimatch": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
- "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
- "license": "ISC",
- "dependencies": {
- "brace-expansion": "^1.1.7"
- },
- "engines": {
- "node": "*"
- }
- },
- "node_modules/ms": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
- "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
- "license": "MIT"
- },
- "node_modules/nanoid": {
- "version": "3.3.7",
- "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
- "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "license": "MIT",
- "bin": {
- "nanoid": "bin/nanoid.cjs"
- },
- "engines": {
- "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
- }
- },
- "node_modules/node-releases": {
- "version": "2.0.14",
- "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz",
- "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==",
- "license": "MIT"
- },
- "node_modules/nodemon": {
- "version": "3.1.4",
- "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.4.tgz",
- "integrity": "sha512-wjPBbFhtpJwmIeY2yP7QF+UKzPfltVGtfce1g/bB15/8vCGZj8uxD62b/b9M9/WVgme0NZudpownKN+c0plXlQ==",
- "license": "MIT",
- "dependencies": {
- "chokidar": "^3.5.2",
- "debug": "^4",
- "ignore-by-default": "^1.0.1",
- "minimatch": "^3.1.2",
- "pstree.remy": "^1.1.8",
- "semver": "^7.5.3",
- "simple-update-notifier": "^2.0.0",
- "supports-color": "^5.5.0",
- "touch": "^3.1.0",
- "undefsafe": "^2.0.5"
- },
- "bin": {
- "nodemon": "bin/nodemon.js"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/nodemon"
- }
- },
- "node_modules/normalize-path": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
- "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/normalize-range": {
- "version": "0.1.2",
- "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz",
- "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==",
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/path-type": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz",
- "integrity": "sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==",
- "license": "MIT",
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/picocolors": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz",
- "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==",
- "license": "ISC"
- },
- "node_modules/picomatch": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
- "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
- "license": "MIT",
- "engines": {
- "node": ">=8.6"
- },
- "funding": {
- "url": "https://github.com/sponsors/jonschlinkert"
- }
- },
- "node_modules/pify": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
- "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==",
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/postcss": {
- "version": "8.4.39",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.39.tgz",
- "integrity": "sha512-0vzE+lAiG7hZl1/9I8yzKLx3aR9Xbof3fBHKunvMfOCYAtMhrsnccJY2iTURb9EZd5+pLuiNV9/c/GZJOHsgIw==",
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/postcss/"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/postcss"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "license": "MIT",
- "dependencies": {
- "nanoid": "^3.3.7",
- "picocolors": "^1.0.1",
- "source-map-js": "^1.2.0"
- },
- "engines": {
- "node": "^10 || ^12 || >=14"
- }
- },
- "node_modules/postcss-cli": {
- "version": "11.0.0",
- "resolved": "https://registry.npmjs.org/postcss-cli/-/postcss-cli-11.0.0.tgz",
- "integrity": "sha512-xMITAI7M0u1yolVcXJ9XTZiO9aO49mcoKQy6pCDFdMh9kGqhzLVpWxeD/32M/QBmkhcGypZFFOLNLmIW4Pg4RA==",
- "license": "MIT",
- "dependencies": {
- "chokidar": "^3.3.0",
- "dependency-graph": "^0.11.0",
- "fs-extra": "^11.0.0",
- "get-stdin": "^9.0.0",
- "globby": "^14.0.0",
- "picocolors": "^1.0.0",
- "postcss-load-config": "^5.0.0",
- "postcss-reporter": "^7.0.0",
- "pretty-hrtime": "^1.0.3",
- "read-cache": "^1.0.0",
- "slash": "^5.0.0",
- "yargs": "^17.0.0"
- },
- "bin": {
- "postcss": "index.js"
- },
- "engines": {
- "node": ">=18"
- },
- "peerDependencies": {
- "postcss": "^8.0.0"
- }
- },
- "node_modules/postcss-load-config": {
- "version": "5.1.0",
- "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-5.1.0.tgz",
- "integrity": "sha512-G5AJ+IX0aD0dygOE0yFZQ/huFFMSNneyfp0e3/bT05a8OfPC5FUoZRPfGijUdGOJNMewJiwzcHJXFafFzeKFVA==",
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/postcss/"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "license": "MIT",
- "dependencies": {
- "lilconfig": "^3.1.1",
- "yaml": "^2.4.2"
- },
- "engines": {
- "node": ">= 18"
- },
- "peerDependencies": {
- "jiti": ">=1.21.0",
- "postcss": ">=8.0.9",
- "tsx": "^4.8.1"
- },
- "peerDependenciesMeta": {
- "jiti": {
- "optional": true
- },
- "postcss": {
- "optional": true
- },
- "tsx": {
- "optional": true
- }
- }
- },
- "node_modules/postcss-reporter": {
- "version": "7.1.0",
- "resolved": "https://registry.npmjs.org/postcss-reporter/-/postcss-reporter-7.1.0.tgz",
- "integrity": "sha512-/eoEylGWyy6/DOiMP5lmFRdmDKThqgn7D6hP2dXKJI/0rJSO1ADFNngZfDzxL0YAxFvws+Rtpuji1YIHj4mySA==",
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/postcss/"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "license": "MIT",
- "dependencies": {
- "picocolors": "^1.0.0",
- "thenby": "^1.3.4"
- },
- "engines": {
- "node": ">=10"
- },
- "peerDependencies": {
- "postcss": "^8.1.0"
- }
- },
- "node_modules/postcss-value-parser": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
- "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
- "license": "MIT"
- },
- "node_modules/pretty-hrtime": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz",
- "integrity": "sha512-66hKPCr+72mlfiSjlEB1+45IjXSqvVAIy6mocupoww4tBFE9R9IhwwUGoI4G++Tc9Aq+2rxOt0RFU6gPcrte0A==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/pstree.remy": {
- "version": "1.1.8",
- "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz",
- "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==",
- "license": "MIT"
- },
- "node_modules/queue-microtask": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
- "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ],
- "license": "MIT"
- },
- "node_modules/read-cache": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
- "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==",
- "license": "MIT",
- "dependencies": {
- "pify": "^2.3.0"
- }
- },
- "node_modules/readdirp": {
- "version": "3.6.0",
- "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
- "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
- "license": "MIT",
- "dependencies": {
- "picomatch": "^2.2.1"
- },
- "engines": {
- "node": ">=8.10.0"
- }
- },
- "node_modules/require-directory": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
- "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/reusify": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
- "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
- "license": "MIT",
- "engines": {
- "iojs": ">=1.0.0",
- "node": ">=0.10.0"
- }
- },
- "node_modules/run-parallel": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
- "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ],
- "license": "MIT",
- "dependencies": {
- "queue-microtask": "^1.2.2"
- }
- },
- "node_modules/sass": {
- "version": "1.77.8",
- "resolved": "https://registry.npmjs.org/sass/-/sass-1.77.8.tgz",
- "integrity": "sha512-4UHg6prsrycW20fqLGPShtEvo/WyHRVRHwOP4DzkUrObWoWI05QBSfzU71TVB7PFaL104TwNaHpjlWXAZbQiNQ==",
- "license": "MIT",
- "dependencies": {
- "chokidar": ">=3.0.0 <4.0.0",
- "immutable": "^4.0.0",
- "source-map-js": ">=0.6.2 <2.0.0"
- },
- "bin": {
- "sass": "sass.js"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/semver": {
- "version": "7.6.2",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz",
- "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==",
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/simple-update-notifier": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz",
- "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==",
- "license": "MIT",
- "dependencies": {
- "semver": "^7.5.3"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/slash": {
- "version": "5.1.0",
- "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz",
- "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==",
- "license": "MIT",
- "engines": {
- "node": ">=14.16"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/source-map-js": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz",
- "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==",
- "license": "BSD-3-Clause",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/spark-md5": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/spark-md5/-/spark-md5-3.0.2.tgz",
- "integrity": "sha512-wcFzz9cDfbuqe0FZzfi2or1sgyIrsDwmPwfZC4hiNidPdPINjeUwNfv5kldczoEAcjl9Y1L3SM7Uz2PUEQzxQw==",
- "license": "(WTFPL OR MIT)"
- },
- "node_modules/string-width": {
- "version": "4.2.3",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
- "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
- "license": "MIT",
- "dependencies": {
- "emoji-regex": "^8.0.0",
- "is-fullwidth-code-point": "^3.0.0",
- "strip-ansi": "^6.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/strip-ansi": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
- "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
- "license": "MIT",
- "dependencies": {
- "ansi-regex": "^5.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/supports-color": {
- "version": "5.5.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
- "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
- "license": "MIT",
- "dependencies": {
- "has-flag": "^3.0.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/tabby-agent": {
- "version": "1.7.0",
- "resolved": "https://registry.npmjs.org/tabby-agent/-/tabby-agent-1.7.0.tgz",
- "integrity": "sha512-jA8cCO39V+nOvFZP3GaXlxQEqqwXJvvz9tlgVFcqbq2gcWTBSUV4SbxoPYDRKIhY27oTXfeG0SHkAaoL+km5GA==",
- "dev": true,
- "bin": {
- "tabby-agent": "dist/node/index.js"
- },
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/thenby": {
- "version": "1.3.4",
- "resolved": "https://registry.npmjs.org/thenby/-/thenby-1.3.4.tgz",
- "integrity": "sha512-89Gi5raiWA3QZ4b2ePcEwswC3me9JIg+ToSgtE0JWeCynLnLxNr/f9G+xfo9K+Oj4AFdom8YNJjibIARTJmapQ==",
- "license": "Apache-2.0"
- },
- "node_modules/to-regex-range": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
- "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
- "license": "MIT",
- "dependencies": {
- "is-number": "^7.0.0"
- },
- "engines": {
- "node": ">=8.0"
- }
- },
- "node_modules/touch": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.1.tgz",
- "integrity": "sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==",
- "license": "ISC",
- "bin": {
- "nodetouch": "bin/nodetouch.js"
- }
- },
- "node_modules/trix": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/trix/-/trix-2.1.3.tgz",
- "integrity": "sha512-LqMp67LiKMQytAHKqNL1Jgmfz69ViW+WBOQTPA2BlMIuxic1mw5vHgDtOE0bvvojUdjAxh0EJtLpJn6BC/2JKw==",
- "license": "MIT"
- },
- "node_modules/undefsafe": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz",
- "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==",
- "license": "MIT"
- },
- "node_modules/unicorn-magic": {
- "version": "0.1.0",
- "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz",
- "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==",
- "license": "MIT",
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/universalify": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
- "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
- "license": "MIT",
- "engines": {
- "node": ">= 10.0.0"
- }
- },
- "node_modules/update-browserslist-db": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz",
- "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==",
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/browserslist"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/browserslist"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "license": "MIT",
- "dependencies": {
- "escalade": "^3.1.2",
- "picocolors": "^1.0.1"
- },
- "bin": {
- "update-browserslist-db": "cli.js"
- },
- "peerDependencies": {
- "browserslist": ">= 4.21.0"
- }
- },
- "node_modules/wrap-ansi": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
- "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
- "license": "MIT",
- "dependencies": {
- "ansi-styles": "^4.0.0",
- "string-width": "^4.1.0",
- "strip-ansi": "^6.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
- }
- },
- "node_modules/y18n": {
- "version": "5.0.8",
- "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
- "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
- "license": "ISC",
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/yaml": {
- "version": "2.4.5",
- "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.5.tgz",
- "integrity": "sha512-aBx2bnqDzVOyNKfsysjA2ms5ZlnjSAW2eG3/L5G/CSujfjLJTJsEw1bGw8kCf04KodQWk1pxlGnZ56CRxiawmg==",
- "license": "ISC",
- "bin": {
- "yaml": "bin.mjs"
- },
- "engines": {
- "node": ">= 14"
- }
- },
- "node_modules/yargs": {
- "version": "17.7.2",
- "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
- "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
- "license": "MIT",
- "dependencies": {
- "cliui": "^8.0.1",
- "escalade": "^3.1.1",
- "get-caller-file": "^2.0.5",
- "require-directory": "^2.1.1",
- "string-width": "^4.2.3",
- "y18n": "^5.0.5",
- "yargs-parser": "^21.1.1"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/yargs-parser": {
- "version": "21.1.1",
- "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
- "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
- "license": "ISC",
- "engines": {
- "node": ">=12"
- }
- }
- }
-}
diff --git a/package.json b/package.json
index 148b0d9..c32d279 100644
--- a/package.json
+++ b/package.json
@@ -8,6 +8,7 @@
"@popperjs/core": "^2.11.8",
"@rails/actiontext": "^7.1.3-4",
"@rails/request.js": "^0.0.11",
+ "@stimulus-components/lightbox": "^4.0.0",
"autoprefixer": "^10.4.19",
"bootstrap": "^5.3.3",
"bootstrap-icons": "^1.11.3",
@@ -30,6 +31,8 @@
"defaults"
],
"devDependencies": {
- "tabby-agent": "^1.7.0"
+ "tabby-agent": "^1.7.0",
+ "vscode-css-languageserver-bin": "^1.4.0",
+ "vscode-langservers-extracted": "^4.10.0"
}
}
\ No newline at end of file
diff --git a/test/controllers/checks_controller_test.rb b/test/controllers/checks_controller_test.rb
index f66c842..669e480 100644
--- a/test/controllers/checks_controller_test.rb
+++ b/test/controllers/checks_controller_test.rb
@@ -8,7 +8,7 @@ class ChecksControllerTest < ::ControllerTest
end
setup do
- @principle = principles(:one)
+ @guideline = guidelines(:one)
@check = checks(:deletable)
User.create!(email_address: "test@example.com", password: "password")
login("test@example.com", "password")
@@ -27,7 +27,7 @@ class ChecksControllerTest < ::ControllerTest
test "should create check" do
assert_difference("Check.count") do
post checks_url,
- params: { check: { principle_id: @principle.id, number: Check.maximum(:number) + 1, level: @check.level, name_de: @check.name_de, position: @check.position,
+ params: { check: { guideline_id: @guideline.id, number: Check.maximum(:number) + 1, level: @check.level, name_de: @check.name_de, position: @check.position,
criterion_de: @check.criterion_de } }
end
@@ -46,7 +46,7 @@ class ChecksControllerTest < ::ControllerTest
test "should update check" do
patch check_url(@check),
- params: { check: { principle_id: @principle.id, level: @check.level, name_de: @check.t_name, position: @check.position,
+ params: { check: { guideline_id: @guideline.id, level: @check.level, name_de: @check.t_name, position: @check.position,
criterion_de: @check.criterion_de } }
assert_redirected_to check_url(@check)
end
diff --git a/test/controllers/guidelines_controller_test.rb b/test/controllers/guidelines_controller_test.rb
new file mode 100644
index 0000000..cf37063
--- /dev/null
+++ b/test/controllers/guidelines_controller_test.rb
@@ -0,0 +1,49 @@
+require "test_helper"
+
+class GuidelinesControllerTest < ActionDispatch::IntegrationTest
+ setup do
+ skip "login"
+ @guideline = guidelines(:one)
+ end
+
+ test "should get index" do
+ get guidelines_url
+ assert_response :success
+ end
+
+ test "should get new" do
+ get new_guideline_url
+ assert_response :success
+ end
+
+ test "should create guideline" do
+ assert_difference("Guideline.count") do
+ post guidelines_url, params: { guideline: { name_de: @guideline.name_de, number: @guideline.number, principle_id: @guideline.principle_id } }
+ end
+
+ assert_redirected_to guideline_url(Guideline.last)
+ end
+
+ test "should show guideline" do
+ get guideline_url(@guideline)
+ assert_response :success
+ end
+
+ test "should get edit" do
+ get edit_guideline_url(@guideline)
+ assert_response :success
+ end
+
+ test "should update guideline" do
+ patch guideline_url(@guideline), params: { guideline: { name_de: @guideline.name_de, number: @guideline.number, principle_id: @guideline.principle_id } }
+ assert_redirected_to guideline_url(@guideline)
+ end
+
+ test "should destroy guideline" do
+ assert_difference("Guideline.count", -1) do
+ delete guideline_url(@guideline)
+ end
+
+ assert_redirected_to guidelines_url
+ end
+end
diff --git a/test/controllers/projects_controller_test.rb b/test/controllers/projects_controller_test.rb
new file mode 100644
index 0000000..c2514b6
--- /dev/null
+++ b/test/controllers/projects_controller_test.rb
@@ -0,0 +1,55 @@
+require "test_helper"
+
+class ProjectsControllerTest < ::ControllerTest
+ teardown do
+ logout
+ end
+
+ setup do
+ @project = projects(:one)
+ User.create!(email_address: "test@example.com", password: "password")
+ login("test@example.com", "password")
+ end
+
+ test "should get index" do
+ get projects_url
+ assert_response :success
+ end
+
+ test "should get new" do
+ get new_project_url
+ assert_response :success
+ end
+
+ test "should create project" do
+ assert_difference("Project.count") do
+ post projects_url, params: { project: { name: @project.name } }
+ end
+
+ assert_redirected_to project_url(Project.last)
+ end
+
+ test "should show project" do
+ get project_url(@project)
+ assert_response :success
+ end
+
+ test "should get edit" do
+ get edit_project_url(@project)
+ assert_response :success
+ end
+
+ test "should update project" do
+ patch project_url(@project), params: { project: { name: @project.name } }
+ assert_redirected_to project_url(@project)
+ end
+
+ test "should destroy project" do
+ p = Project.create!(name: "empty")
+ assert_difference("Project.count", -1) do
+ delete project_url(p)
+ end
+
+ assert_redirected_to projects_url
+ end
+end
diff --git a/test/controllers/reports_controller_test.rb b/test/controllers/reports_controller_test.rb
index f46759f..0b9f9e7 100644
--- a/test/controllers/reports_controller_test.rb
+++ b/test/controllers/reports_controller_test.rb
@@ -14,18 +14,18 @@ class ReportsControllerTest < ::ControllerTest
end
test "should get index" do
- get reports_url
+ get project_reports_url(@report.project)
assert_response :success
end
test "should get new" do
- get new_report_url
+ get new_project_report_url(@report.project)
assert_response :success
end
test "should create report" do
assert_difference("Report.count") do
- post reports_url, params: { report: { comment: @report.comment, name: @report.name } }
+ post project_reports_url(@report.project), params: { report: { comment: @report.comment, name: @report.name } }
end
assert_redirected_to report_url(Report.last)
@@ -51,6 +51,6 @@ class ReportsControllerTest < ::ControllerTest
delete report_url(@report)
end
- assert_redirected_to reports_url
+ assert_redirected_to project_url(@report.project)
end
end
diff --git a/test/fixtures/checks.yml b/test/fixtures/checks.yml
index afadaf9..29d2a96 100644
--- a/test/fixtures/checks.yml
+++ b/test/fixtures/checks.yml
@@ -5,18 +5,18 @@ one:
name_de: MyString
level: 1
number: 1
- principle: one
+ guideline: one
two:
position: MyString
name_de: MyString
level: 1
number: 2
- principle: one
+ guideline: one
deletable:
position: MyString
name_de: MyString
level: 1
number: 3
- principle: one
+ guideline: one
diff --git a/test/fixtures/guidelines.yml b/test/fixtures/guidelines.yml
new file mode 100644
index 0000000..63db8d4
--- /dev/null
+++ b/test/fixtures/guidelines.yml
@@ -0,0 +1,11 @@
+# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
+
+one:
+ principle: one
+ number: 1
+ name_de: MyString
+
+two:
+ principle: two
+ number: 1
+ name_de: MyString
diff --git a/test/fixtures/projects.yml b/test/fixtures/projects.yml
new file mode 100644
index 0000000..7d41224
--- /dev/null
+++ b/test/fixtures/projects.yml
@@ -0,0 +1,7 @@
+# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
+
+one:
+ name: MyString
+
+two:
+ name: MyString
diff --git a/test/fixtures/reports.yml b/test/fixtures/reports.yml
index 7d41224..169701e 100644
--- a/test/fixtures/reports.yml
+++ b/test/fixtures/reports.yml
@@ -2,6 +2,8 @@
one:
name: MyString
+ project: one
two:
name: MyString
+ project: one
diff --git a/test/models/guideline_test.rb b/test/models/guideline_test.rb
new file mode 100644
index 0000000..eb514f4
--- /dev/null
+++ b/test/models/guideline_test.rb
@@ -0,0 +1,7 @@
+require "test_helper"
+
+class GuidelineTest < ActiveSupport::TestCase
+ # test "the truth" do
+ # assert true
+ # end
+end
diff --git a/test/models/project_test.rb b/test/models/project_test.rb
new file mode 100644
index 0000000..5df4ca4
--- /dev/null
+++ b/test/models/project_test.rb
@@ -0,0 +1,7 @@
+require "test_helper"
+
+class ProjectTest < ActiveSupport::TestCase
+ # test "the truth" do
+ # assert true
+ # end
+end
diff --git a/test/system/guidelines_test.rb b/test/system/guidelines_test.rb
new file mode 100644
index 0000000..f108ac9
--- /dev/null
+++ b/test/system/guidelines_test.rb
@@ -0,0 +1,45 @@
+require "application_system_test_case"
+
+class GuidelinesTest < ApplicationSystemTestCase
+ setup do
+ @guideline = guidelines(:one)
+ end
+
+ test "visiting the index" do
+ visit guidelines_url
+ assert_selector "h1", text: "Guidelines"
+ end
+
+ test "should create guideline" do
+ visit guidelines_url
+ click_on "New guideline"
+
+ fill_in "Name de", with: @guideline.name_de
+ fill_in "Number", with: @guideline.number
+ fill_in "Principle", with: @guideline.principle_id
+ click_on "Create Guideline"
+
+ assert_text "Guideline was successfully created"
+ click_on "Back"
+ end
+
+ test "should update Guideline" do
+ visit guideline_url(@guideline)
+ click_on "Edit this guideline", match: :first
+
+ fill_in "Name de", with: @guideline.name_de
+ fill_in "Number", with: @guideline.number
+ fill_in "Principle", with: @guideline.principle_id
+ click_on "Update Guideline"
+
+ assert_text "Guideline was successfully updated"
+ click_on "Back"
+ end
+
+ test "should destroy Guideline" do
+ visit guideline_url(@guideline)
+ click_on "Destroy this guideline", match: :first
+
+ assert_text "Guideline was successfully destroyed"
+ end
+end
diff --git a/test/system/projects_test.rb b/test/system/projects_test.rb
new file mode 100644
index 0000000..2134947
--- /dev/null
+++ b/test/system/projects_test.rb
@@ -0,0 +1,47 @@
+require "application_system_test_case"
+
+class ProjectsTest < ApplicationSystemTestCase
+ setup do
+ @project = projects(:one)
+ login_test
+ end
+
+ teardown do
+ logout
+ end
+
+ test "visiting the index" do
+ visit projects_url
+ assert_selector "h1", text: "Projekte"
+ end
+
+ test "should create project" do
+ visit projects_url
+ click_on "Projekt hinzufügen"
+
+ fill_in "Name", with: @project.name
+ click_on "Projekt erstellen"
+
+ assert_text "Project was successfully created"
+ click_on "Projekte Liste"
+ end
+
+ test "should update Project" do
+ visit project_url(@project)
+ click_on "Projekt bearbeiten", match: :first
+
+ fill_in "Name", with: @project.name
+ click_on "Projekt aktualisieren"
+
+ assert_text "Project was successfully updated"
+ click_on "Projekte Liste"
+ end
+
+ test "should destroy Project" do
+ empty = Project.create!(name: "empty")
+ visit project_url(empty)
+ click_on "Projekt löschen", match: :first
+
+ assert_text "Project was successfully destroyed"
+ end
+end
diff --git a/test/system/reports_test.rb b/test/system/reports_test.rb
index 6703232..c7a5ec3 100644
--- a/test/system/reports_test.rb
+++ b/test/system/reports_test.rb
@@ -13,12 +13,12 @@ class ReportsTest < ApplicationSystemTestCase
end
test "visiting the index" do
- visit reports_url
+ visit project_reports_url(@report.project)
assert_selector "h1", text: "Prüfberichte"
end
test "should create report" do
- visit reports_url
+ visit project_reports_url(@report.project)
click_on "Prüfbericht hinzufügen"
fill_in_rich_text_area "Projektbeschreibung", with: @report.comment
@@ -37,7 +37,9 @@ class ReportsTest < ApplicationSystemTestCase
test "should destroy Report" do
visit report_url(@report)
- click_on "Prüfbericht löschen", match: :first
+ accept_confirm do
+ click_on "Prüfbericht löschen", match: :first
+ end
assert_text("Prüfberichte")
assert(Report.exists?(@report.id) == false)
end
diff --git a/tmp/pids/.keep b/tmp/pids/.keep
deleted file mode 100644
index e69de29..0000000
diff --git a/vendor/assets/fonts/lg.svg b/vendor/assets/fonts/lg.svg
new file mode 100644
index 0000000..fe8b075
--- /dev/null
+++ b/vendor/assets/fonts/lg.svg
@@ -0,0 +1,54 @@
+
+
+
\ No newline at end of file
diff --git a/vendor/assets/fonts/lg.ttf b/vendor/assets/fonts/lg.ttf
new file mode 100644
index 0000000..825f483
Binary files /dev/null and b/vendor/assets/fonts/lg.ttf differ
diff --git a/vendor/assets/fonts/lg.woff b/vendor/assets/fonts/lg.woff
new file mode 100644
index 0000000..fd02a6f
Binary files /dev/null and b/vendor/assets/fonts/lg.woff differ
diff --git a/vendor/assets/fonts/lg.woff2 b/vendor/assets/fonts/lg.woff2
new file mode 100644
index 0000000..2c2e289
Binary files /dev/null and b/vendor/assets/fonts/lg.woff2 differ
diff --git a/vendor/assets/images/loading.gif b/vendor/assets/images/loading.gif
new file mode 100644
index 0000000..4744c45
Binary files /dev/null and b/vendor/assets/images/loading.gif differ
diff --git a/yarn.lock b/yarn.lock
index bf77f5c..135b0bf 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -124,7 +124,7 @@
"@github/hotkey@^3.1.1":
version "3.1.1"
- resolved "https://registry.yarnpkg.com/@github/hotkey/-/hotkey-3.1.1.tgz#61fdf9993378b402bd9cdd494ee8149fe3172b0c"
+ resolved "https://registry.npmjs.org/@github/hotkey/-/hotkey-3.1.1.tgz"
integrity sha512-H30I6XDO3gFSgLuEuHoMBRZG9c3uCKNdAcYklL1FaZDPdU1bXfgjnpzGDPcUr0U6eGQ+T3XLY9slatwZYWL1dA==
"@hotwired/stimulus@^3.2.2":
@@ -192,7 +192,7 @@
"@rails/request.js@^0.0.11":
version "0.0.11"
- resolved "https://registry.yarnpkg.com/@rails/request.js/-/request.js-0.0.11.tgz#4d9be25a49d97911c64ccd0f00b79d57fca4c3b4"
+ resolved "https://registry.npmjs.org/@rails/request.js/-/request.js-0.0.11.tgz"
integrity sha512-2U3uYS0kbljt+pAstN+LIlZOl7xmOKig5N6FrvtUWO1wq0zR1Hf90fHfD2SYiyV8yH1nyKpoTmbLqWT0xe1zDg==
"@sindresorhus/merge-streams@^2.1.0":
@@ -200,6 +200,23 @@
resolved "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz"
integrity sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==
+"@stimulus-components/lightbox@^4.0.0":
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/@stimulus-components/lightbox/-/lightbox-4.0.0.tgz#dbe56146a3d14582a13e568406292d52aa56cbb0"
+ integrity sha512-pj4PfnGANbc3Ef6I/5aPeRS8Tj2rK1b9dn8rlpJZs1K9narqM57ZtUTutHZsnOv95+4LqQVktj+auMgz+LKzjw==
+ dependencies:
+ lightgallery "^2.7.2"
+
+"@vscode/l10n@^0.0.10":
+ version "0.0.10"
+ resolved "https://registry.npmjs.org/@vscode/l10n/-/l10n-0.0.10.tgz"
+ integrity sha512-E1OCmDcDWa0Ya7vtSjp/XfHFGqYJfh+YPC1RkATU71fTac+j1JjCcB3qwSzmlKAighx2WxhLlfhS0RwAN++PFQ==
+
+"@vscode/l10n@^0.0.18":
+ version "0.0.18"
+ resolved "https://registry.npmjs.org/@vscode/l10n/-/l10n-0.0.18.tgz"
+ integrity sha512-KYSIHVmslkaCDyw013pphY+d7x1qV8IZupYfeIfzNA+nsaWHbn5uPuQRvdRFsa9zFzGeudPuoGoZ1Op4jrJXIQ==
+
ansi-regex@^5.0.1:
version "5.0.1"
resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz"
@@ -242,6 +259,11 @@ binary-extensions@^2.0.0:
resolved "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz"
integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==
+boolbase@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz"
+ integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==
+
bootstrap-icons@^1.11.3:
version "1.11.3"
resolved "https://registry.npmjs.org/bootstrap-icons/-/bootstrap-icons-1.11.3.tgz"
@@ -323,6 +345,27 @@ concat-map@0.0.1:
resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz"
integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==
+core-js@^3.20.1:
+ version "3.39.0"
+ resolved "https://registry.npmjs.org/core-js/-/core-js-3.39.0.tgz"
+ integrity sha512-raM0ew0/jJUqkJ0E6e8UDtl+y/7ktFivgWvqw8dNSQeNWoSDLvQ1H/RN3aPXB9tBd4/FhyR4RDPGhsNIMsAn7g==
+
+css-select@^5.1.0:
+ version "5.1.0"
+ resolved "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz"
+ integrity sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==
+ dependencies:
+ boolbase "^1.0.0"
+ css-what "^6.1.0"
+ domhandler "^5.0.2"
+ domutils "^3.0.1"
+ nth-check "^2.0.1"
+
+css-what@^6.1.0:
+ version "6.1.0"
+ resolved "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz"
+ integrity sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==
+
debug@^4:
version "4.3.5"
resolved "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz"
@@ -335,6 +378,36 @@ dependency-graph@^0.11.0:
resolved "https://registry.npmjs.org/dependency-graph/-/dependency-graph-0.11.0.tgz"
integrity sha512-JeMq7fEshyepOWDfcfHK06N3MhyPhz++vtqWhMT5O9A3K42rdsEDpfdVqjaqaAhsw6a+ZqeDvQVtD0hFHQWrzg==
+dom-serializer@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz"
+ integrity sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==
+ dependencies:
+ domelementtype "^2.3.0"
+ domhandler "^5.0.2"
+ entities "^4.2.0"
+
+domelementtype@^2.3.0:
+ version "2.3.0"
+ resolved "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz"
+ integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==
+
+domhandler@^5.0.2, domhandler@^5.0.3:
+ version "5.0.3"
+ resolved "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz"
+ integrity sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==
+ dependencies:
+ domelementtype "^2.3.0"
+
+domutils@^3.0.1:
+ version "3.1.0"
+ resolved "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz"
+ integrity sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==
+ dependencies:
+ dom-serializer "^2.0.0"
+ domelementtype "^2.3.0"
+ domhandler "^5.0.3"
+
electron-to-chromium@^1.4.820:
version "1.4.827"
resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.827.tgz"
@@ -345,6 +418,11 @@ emoji-regex@^8.0.0:
resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz"
integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==
+entities@^4.2.0:
+ version "4.5.0"
+ resolved "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz"
+ integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==
+
esbuild@^0.23.0:
version "0.23.0"
resolved "https://registry.npmjs.org/esbuild/-/esbuild-0.23.0.tgz"
@@ -463,6 +541,11 @@ has-flag@^3.0.0:
resolved "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz"
integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==
+he@1.2.0:
+ version "1.2.0"
+ resolved "https://registry.npmjs.org/he/-/he-1.2.0.tgz"
+ integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==
+
ignore-by-default@^1.0.1:
version "1.0.1"
resolved "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz"
@@ -507,6 +590,11 @@ is-number@^7.0.0:
resolved "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz"
integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
+jsonc-parser@^3.2.1, jsonc-parser@^3.3.1:
+ version "3.3.1"
+ resolved "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz"
+ integrity sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==
+
jsonfile@^6.0.1:
version "6.1.0"
resolved "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz"
@@ -516,6 +604,11 @@ jsonfile@^6.0.1:
optionalDependencies:
graceful-fs "^4.1.6"
+lightgallery@^2.7.2:
+ version "2.8.1"
+ resolved "https://registry.npmjs.org/lightgallery/-/lightgallery-2.8.1.tgz"
+ integrity sha512-K9bRsrKQM4UyjNUXOX+mW1IMWKvWbDmK42x5nNzgxsi5CNEYMfLoRsA27F1lXp+yegeqdXusymS9w16Fd8a3Rg==
+
lilconfig@^3.1.1:
version "3.1.2"
resolved "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz"
@@ -551,6 +644,14 @@ nanoid@^3.3.7:
resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz"
integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==
+node-html-parser@^6.1.5:
+ version "6.1.13"
+ resolved "https://registry.npmjs.org/node-html-parser/-/node-html-parser-6.1.13.tgz"
+ integrity sha512-qIsTMOY4C/dAa5Q5vsobRpOOvPfC4pB61UVW2uSwZNUp0QU/jCekTal1vMmbO0DgdHeLUJpv/ARmDqErVxA3Sg==
+ dependencies:
+ css-select "^5.1.0"
+ he "1.2.0"
+
node-releases@^2.0.14:
version "2.0.14"
resolved "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz"
@@ -582,6 +683,13 @@ normalize-range@^0.1.2:
resolved "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz"
integrity sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==
+nth-check@^2.0.1:
+ version "2.1.1"
+ resolved "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz"
+ integrity sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==
+ dependencies:
+ boolbase "^1.0.0"
+
path-type@^5.0.0:
version "5.0.0"
resolved "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz"
@@ -679,6 +787,16 @@ readdirp@~3.6.0:
dependencies:
picomatch "^2.2.1"
+regenerator-runtime@^0.13.9:
+ version "0.13.11"
+ resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz"
+ integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==
+
+request-light@^0.7.0:
+ version "0.7.0"
+ resolved "https://registry.npmjs.org/request-light/-/request-light-0.7.0.tgz"
+ integrity sha512-lMbBMrDoxgsyO+yB3sDcrDuX85yYt7sS8BfQd11jtbW/z5ZWgLZRcEGLsLoYw7I0WSUGQBs8CC8ScIxkTX1+6Q==
+
require-directory@^2.1.1:
version "2.1.1"
resolved "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz"
@@ -705,7 +823,7 @@ sass@^1.77.8:
immutable "^4.0.0"
source-map-js ">=0.6.2 <2.0.0"
-semver@^7.5.3:
+semver@^7.5.3, semver@^7.6.1:
version "7.6.2"
resolved "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz"
integrity sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==
@@ -724,7 +842,7 @@ slash@^5.0.0, slash@^5.1.0:
sortablejs@^1.15.3:
version "1.15.3"
- resolved "https://registry.yarnpkg.com/sortablejs/-/sortablejs-1.15.3.tgz#033668db5ebfb11167d1249ab88e748f27959e29"
+ resolved "https://registry.npmjs.org/sortablejs/-/sortablejs-1.15.3.tgz"
integrity sha512-zdK3/kwwAK1cJgy1rwl1YtNTbRmc8qW/+vgXf75A7NHag5of4pyI6uK86ktmQETyWRH7IGaE73uZOOBcGxgqZg==
"source-map-js@>=0.6.2 <2.0.0", source-map-js@^1.2.0:
@@ -787,6 +905,11 @@ trix@^2.1.3:
resolved "https://registry.npmjs.org/trix/-/trix-2.1.3.tgz"
integrity sha512-LqMp67LiKMQytAHKqNL1Jgmfz69ViW+WBOQTPA2BlMIuxic1mw5vHgDtOE0bvvojUdjAxh0EJtLpJn6BC/2JKw==
+typescript@^4.0.5:
+ version "4.9.5"
+ resolved "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz"
+ integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==
+
undefsafe@^2.0.5:
version "2.0.5"
resolved "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz"
@@ -810,6 +933,172 @@ update-browserslist-db@^1.1.0:
escalade "^3.1.2"
picocolors "^1.0.1"
+vscode-css-languageserver-bin@^1.4.0:
+ version "1.4.0"
+ resolved "https://registry.npmjs.org/vscode-css-languageserver-bin/-/vscode-css-languageserver-bin-1.4.0.tgz"
+ integrity sha512-KWrF5f4RYYe8RBDfqb1c0Sdf9xPS2Ly/Z/T18H+uUOMw2QyzIrkxv4bMKy5GFfPm4479k6Ln4ji4UHqSmhGf3g==
+ dependencies:
+ vscode-css-languageservice "^3.0.9-next.18"
+ vscode-languageserver "^4.1.3"
+ vscode-languageserver-protocol-foldingprovider "^2.0.1"
+
+vscode-css-languageservice@^3.0.9-next.18:
+ version "3.0.13"
+ resolved "https://registry.npmjs.org/vscode-css-languageservice/-/vscode-css-languageservice-3.0.13.tgz"
+ integrity sha512-RWkO/c/A7iXhHEy3OuEqkCqavDjpD4NF2Ca8vjai+ZtEYNeHrm1ybTnBYLP4Ft1uXvvaaVtYA9HrDjD6+CUONg==
+ dependencies:
+ vscode-languageserver-types "^3.13.0"
+ vscode-nls "^4.0.0"
+
+vscode-css-languageservice@^6.2.14:
+ version "6.3.1"
+ resolved "https://registry.npmjs.org/vscode-css-languageservice/-/vscode-css-languageservice-6.3.1.tgz"
+ integrity sha512-1BzTBuJfwMc3A0uX4JBdJgoxp74cjj4q2mDJdp49yD/GuAq4X0k5WtK6fNcMYr+FfJ9nqgR6lpfCSZDkARJ5qQ==
+ dependencies:
+ "@vscode/l10n" "^0.0.18"
+ vscode-languageserver-textdocument "^1.0.12"
+ vscode-languageserver-types "3.17.5"
+ vscode-uri "^3.0.8"
+
+vscode-html-languageservice@^5.2.0:
+ version "5.3.1"
+ resolved "https://registry.npmjs.org/vscode-html-languageservice/-/vscode-html-languageservice-5.3.1.tgz"
+ integrity sha512-ysUh4hFeW/WOWz/TO9gm08xigiSsV/FOAZ+DolgJfeLftna54YdmZ4A+lIn46RbdO3/Qv5QHTn1ZGqmrXQhZyA==
+ dependencies:
+ "@vscode/l10n" "^0.0.18"
+ vscode-languageserver-textdocument "^1.0.12"
+ vscode-languageserver-types "^3.17.5"
+ vscode-uri "^3.0.8"
+
+vscode-json-languageservice@^5.3.11:
+ version "5.4.1"
+ resolved "https://registry.npmjs.org/vscode-json-languageservice/-/vscode-json-languageservice-5.4.1.tgz"
+ integrity sha512-5czFGNyVPxz3ZJYl8R3a3SuIj5gjhmGF4Wv05MRPvD4DEnHK6b8km4VbNMJNHBlTCh7A0aHzUbPVzo+0C18mCA==
+ dependencies:
+ "@vscode/l10n" "^0.0.18"
+ jsonc-parser "^3.3.1"
+ vscode-languageserver-textdocument "^1.0.12"
+ vscode-languageserver-types "^3.17.5"
+ vscode-uri "^3.0.8"
+
+vscode-jsonrpc@8.2.0:
+ version "8.2.0"
+ resolved "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz"
+ integrity sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==
+
+vscode-jsonrpc@9.0.0-next.6:
+ version "9.0.0-next.6"
+ resolved "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-9.0.0-next.6.tgz"
+ integrity sha512-KCSvUNsFiVciG9iqjJKBZOd66CN3ZKohDlYRmoOi+pd8l15MFLZ8wRG4c+wuzePGba/8WcCG2TM+C/GVlvuaeA==
+
+vscode-langservers-extracted@^4.10.0:
+ version "4.10.0"
+ resolved "https://registry.npmjs.org/vscode-langservers-extracted/-/vscode-langservers-extracted-4.10.0.tgz"
+ integrity sha512-EFf9uQI4dAKbzMQFjDvVm1xJq1DXAQvBEuEfPGrK/xzfsL5xWTfIuRr90NgfmqwO+IEt6vLZm9EOj6R66xIifg==
+ dependencies:
+ "@vscode/l10n" "^0.0.18"
+ core-js "^3.20.1"
+ jsonc-parser "^3.2.1"
+ regenerator-runtime "^0.13.9"
+ request-light "^0.7.0"
+ semver "^7.6.1"
+ typescript "^4.0.5"
+ vscode-css-languageservice "^6.2.14"
+ vscode-html-languageservice "^5.2.0"
+ vscode-json-languageservice "^5.3.11"
+ vscode-languageserver "^10.0.0-next.3"
+ vscode-languageserver-textdocument "^1.0.11"
+ vscode-languageserver-types "^3.17.5"
+ vscode-markdown-languageservice "^0.5.0-alpha.6"
+ vscode-nls "^5.2.0"
+ vscode-uri "^3.0.8"
+
+vscode-languageserver-protocol-foldingprovider@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.npmjs.org/vscode-languageserver-protocol-foldingprovider/-/vscode-languageserver-protocol-foldingprovider-2.0.1.tgz"
+ integrity sha512-N8bOS8i0xuQMn/y0bijyefDbOsMl6hiH6LDREYWavTLTM5jbj44EiQfStsbmAv/0eaFKkL/jf5hW7nWwBy2HBw==
+ dependencies:
+ vscode-languageserver-protocol "^3.7.2"
+ vscode-languageserver-types "^3.7.2"
+
+vscode-languageserver-protocol@3.17.6-next.11:
+ version "3.17.6-next.11"
+ resolved "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.6-next.11.tgz"
+ integrity sha512-GeJxEp1TiLsp79f8WG5n10wLViXfgFKb99hU9K8m7KDWM95/QFEqWkm79f9LVm54tUK74I91a9EeiQLCS/FABQ==
+ dependencies:
+ vscode-jsonrpc "9.0.0-next.6"
+ vscode-languageserver-types "3.17.6-next.5"
+
+vscode-languageserver-protocol@^3.10.3, vscode-languageserver-protocol@^3.17.1, vscode-languageserver-protocol@^3.7.2:
+ version "3.17.5"
+ resolved "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz"
+ integrity sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==
+ dependencies:
+ vscode-jsonrpc "8.2.0"
+ vscode-languageserver-types "3.17.5"
+
+vscode-languageserver-textdocument@^1.0.11, vscode-languageserver-textdocument@^1.0.12:
+ version "1.0.12"
+ resolved "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.12.tgz"
+ integrity sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA==
+
+vscode-languageserver-types@3.17.5, vscode-languageserver-types@^3.13.0, vscode-languageserver-types@^3.17.5, vscode-languageserver-types@^3.7.2:
+ version "3.17.5"
+ resolved "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz"
+ integrity sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==
+
+vscode-languageserver-types@3.17.6-next.5:
+ version "3.17.6-next.5"
+ resolved "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.6-next.5.tgz"
+ integrity sha512-QFmf3Yl1tCgUQfA77N9Me/LXldJXkIVypQbty2rJ1DNHQkC+iwvm4Z2tXg9czSwlhvv0pD4pbF5mT7WhAglolw==
+
+vscode-languageserver@^10.0.0-next.3:
+ version "10.0.0-next.11"
+ resolved "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-10.0.0-next.11.tgz"
+ integrity sha512-cmobSrVDYhlh/t02vz/bV8nNpds8mus5HnILULae2iAvOjoaJPnTAp0jJWoYdUqTpIVzT9JV6JMKqLEvdqpeqg==
+ dependencies:
+ vscode-languageserver-protocol "3.17.6-next.11"
+
+vscode-languageserver@^4.1.3:
+ version "4.4.2"
+ resolved "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-4.4.2.tgz"
+ integrity sha512-61y8Raevi9EigDgg9NelvT9cUAohiEbUl1LOwQQgOCAaNX62yKny/ddi0uC+FUTm4CzsjhBu+06R+vYgfCYReA==
+ dependencies:
+ vscode-languageserver-protocol "^3.10.3"
+ vscode-uri "^1.0.5"
+
+vscode-markdown-languageservice@^0.5.0-alpha.6:
+ version "0.5.0-alpha.8"
+ resolved "https://registry.npmjs.org/vscode-markdown-languageservice/-/vscode-markdown-languageservice-0.5.0-alpha.8.tgz"
+ integrity sha512-b2NgVMZvzI/7hRL32Kcu9neAAPFQzkcf/Fqwlxbz9p1/Q7aIorGACOGGo00s72AJtwjkCJ29eVJwUlFMFbPKqA==
+ dependencies:
+ "@vscode/l10n" "^0.0.10"
+ node-html-parser "^6.1.5"
+ picomatch "^2.3.1"
+ vscode-languageserver-protocol "^3.17.1"
+ vscode-languageserver-textdocument "^1.0.11"
+ vscode-uri "^3.0.7"
+
+vscode-nls@^4.0.0:
+ version "4.1.2"
+ resolved "https://registry.npmjs.org/vscode-nls/-/vscode-nls-4.1.2.tgz"
+ integrity sha512-7bOHxPsfyuCqmP+hZXscLhiHwe7CSuFE4hyhbs22xPIhQ4jv99FcR4eBzfYYVLP356HNFpdvz63FFb/xw6T4Iw==
+
+vscode-nls@^5.2.0:
+ version "5.2.0"
+ resolved "https://registry.npmjs.org/vscode-nls/-/vscode-nls-5.2.0.tgz"
+ integrity sha512-RAaHx7B14ZU04EU31pT+rKz2/zSl7xMsfIZuo8pd+KZO6PXtQmpevpq3vxvWNcrGbdmhM/rr5Uw5Mz+NBfhVng==
+
+vscode-uri@^1.0.5:
+ version "1.0.8"
+ resolved "https://registry.npmjs.org/vscode-uri/-/vscode-uri-1.0.8.tgz"
+ integrity sha512-obtSWTlbJ+a+TFRYGaUumtVwb+InIUVI0Lu0VBUAPmj2cU5JutEXg3xUE0c2J5Tcy7h2DEKVJBFi+Y9ZSFzzPQ==
+
+vscode-uri@^3.0.7, vscode-uri@^3.0.8:
+ version "3.0.8"
+ resolved "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.8.tgz"
+ integrity sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==
+
wrap-ansi@^7.0.0:
version "7.0.0"
resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz"