Compare commits

..

No commits in common. "main" and "alpha-deployment" have entirely different histories.

149 changed files with 2121 additions and 2778 deletions

View file

@ -41,5 +41,3 @@
/.forgejo/
/core*
/.devenv

2
.gitignore vendored
View file

@ -74,5 +74,3 @@ public/504.html
public/505.html
public/507.html
public/510.html
/.devenv

View file

@ -1 +1 @@
ruby-3.4
ruby-3.3.5

View file

@ -1,19 +1,19 @@
ARG RUBY_VERSION=3.4
ARG NAME=app
ARG UID=1000
ARG GID=1000
ARG INSTALL_DIR=/home/${NAME}/src
FROM ruby:${RUBY_VERSION} as development
LABEL maintainer='david@hohl.cloud'
ARG APP_PORT=3000
ARG INSTALL_DIR=/${NAME}
ARG RUBY_VERSION=3.2.5
FROM ruby:${RUBY_VERSION} AS development
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,7 +39,6 @@ RUN \
--disabled-login \
--shell /bin/bash \
${NAME} && \
chown -R ${NAME}:${NAME} /home/${NAME} && \
apt-get update && \
apt-get install -yqq --no-install-recommends \
gnupg2 \
@ -48,8 +47,9 @@ 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 libjemalloc2 && \
sqlite3 nodejs npm sassc yarn libvips fish ranger pandoc libjemalloc2 && \
apt-get clean && \
npm install tabby-agent && \
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* && \
truncate -s 0 /var/log/*log && \
gem update --system && \
@ -57,91 +57,135 @@ RUN \
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"]
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
CMD ["/bin/sh", "-c", "dev"]
FROM development AS build
USER root
# 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
COPY ./Gemfile ./Gemfile.lock ./
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 . .
RUN bundle exec bootsnap precompile app/ lib/ && \
rails assets:precompile && \
rm -rf log/* tmp/* && \
chown -R ${NAME}:${NAME} log tmp
FROM ruby:${RUBY_VERSION}-slim AS release
FROM ruby:${RUBY_VERSION}-alpine AS builder
ARG NAME
ARG UID
ARG GID
ARG NAME=app
ARG APP_PORT
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}
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/* && \
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 && \
truncate -s 0 /var/log/*log
bundle config set app_config ${GEM_HOME}
ENV LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.2
RUN pwd
USER ${NAME}
COPY --from=build ${GEM_HOME} ${GEM_HOME}
COPY --from=build ${BUILD_DIR} .
USER root
RUN ls -la && chown -R ${NAME}:${NAME} ./tmp ./log ./storage
COPY Gemfile Gemfile.lock package.json yarn.lock ./
RUN bundle config without test development && bundle install && yarn install
FROM builder AS assets
COPY . .
COPY --from=builder ${INSTALL_DIR}/.bundle ${INSTALL_DIR}/.bundle
COPY --from=builder ${INSTALL_DIR}/node_modules ${INSTALL_DIR}/node_modules
RUN RAILS_ENV=production SECRET_KEY_BASE_DUMMY=1 rails assets:precompile
FROM ruby:${RUBY_VERSION}-alpine AS production
ARG INSTALL_DIR
ARG NAME
WORKDIR ${INSTALL_DIR}
ENV GEM_HOME=${INSTALL_DIR}/.bundle
ENV \
RAILS_ENV=production \
PATH=${INSTALL_DIR}/bin:$GEM_HOME/bin:$GEM_HOME/gems/bin:$PATH \
TZ=Europe/Zurich
RUN \
adduser ${NAME} --disabled-password --shell /bin/ash && \
apk add --update --no-cache \
tzdata \
sqlite \
vips-dev \
jemalloc && \
gem update --system && \
bundle config set app_config ${GEM_HOME} && \
bundle config set without development test && \
apk add patchelf && \
patchelf --add-needed libjemalloc.so.2 /usr/local/bin/ruby && \
apk del patchelf && \
truncate -s 0 /var/log/*log
EXPOSE 3000
ENTRYPOINT ["bin/docker-entrypoint"]
COPY . .
COPY --from=builder ${INSTALL_DIR}/.bundle ${INSTALL_DIR}/.bundle
COPY --from=assets ${INSTALL_DIR}/public/assets ${INSTALL_DIR}/public/assets
RUN chown -R ${NAME}:${NAME} ${INSTALL_DIR}/tmp ${INSTALL_DIR}/log ${INSTALL_DIR}/storage && \
date +"%Y-%m-%d %H:%M:%S %Z" >> .build_version
USER ${NAME}
CMD ["./bin/rails", "server", "-b", "0"]
ENTRYPOINT [ "bin/entrypoint" ]
CMD [ "rails", "server", "--binding", "0.0.0.0", "--no-daemon", "--port" , "3000" ]

View file

@ -2,6 +2,8 @@
source "https://rubygems.org"
ruby "3.2.5"
# Bundle edge Rails instead: gem "rails", github: "rails/rails", branch: "main"
gem "rails", "~> 8.0"
@ -48,7 +50,6 @@ 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"
@ -57,7 +58,6 @@ 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

View file

@ -1,29 +1,29 @@
GEM
remote: https://rubygems.org/
specs:
actioncable (8.0.2)
actionpack (= 8.0.2)
activesupport (= 8.0.2)
actioncable (8.0.0)
actionpack (= 8.0.0)
activesupport (= 8.0.0)
nio4r (~> 2.0)
websocket-driver (>= 0.6.1)
zeitwerk (~> 2.6)
actionmailbox (8.0.2)
actionpack (= 8.0.2)
activejob (= 8.0.2)
activerecord (= 8.0.2)
activestorage (= 8.0.2)
activesupport (= 8.0.2)
actionmailbox (8.0.0)
actionpack (= 8.0.0)
activejob (= 8.0.0)
activerecord (= 8.0.0)
activestorage (= 8.0.0)
activesupport (= 8.0.0)
mail (>= 2.8.0)
actionmailer (8.0.2)
actionpack (= 8.0.2)
actionview (= 8.0.2)
activejob (= 8.0.2)
activesupport (= 8.0.2)
actionmailer (8.0.0)
actionpack (= 8.0.0)
actionview (= 8.0.0)
activejob (= 8.0.0)
activesupport (= 8.0.0)
mail (>= 2.8.0)
rails-dom-testing (~> 2.2)
actionpack (8.0.2)
actionview (= 8.0.2)
activesupport (= 8.0.2)
actionpack (8.0.0)
actionview (= 8.0.0)
activesupport (= 8.0.0)
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.2)
actionpack (= 8.0.2)
activerecord (= 8.0.2)
activestorage (= 8.0.2)
activesupport (= 8.0.2)
actiontext (8.0.0)
actionpack (= 8.0.0)
activerecord (= 8.0.0)
activestorage (= 8.0.0)
activesupport (= 8.0.0)
globalid (>= 0.6.0)
nokogiri (>= 1.8.5)
actionview (8.0.2)
activesupport (= 8.0.2)
actionview (8.0.0)
activesupport (= 8.0.0)
builder (~> 3.1)
erubi (~> 1.11)
rails-dom-testing (~> 2.2)
rails-html-sanitizer (~> 1.6)
activejob (8.0.2)
activesupport (= 8.0.2)
activejob (8.0.0)
activesupport (= 8.0.0)
globalid (>= 0.3.6)
activemodel (8.0.2)
activesupport (= 8.0.2)
activerecord (8.0.2)
activemodel (= 8.0.2)
activesupport (= 8.0.2)
activemodel (8.0.0)
activesupport (= 8.0.0)
activerecord (8.0.0)
activemodel (= 8.0.0)
activesupport (= 8.0.0)
timeout (>= 0.4.0)
activestorage (8.0.2)
actionpack (= 8.0.2)
activejob (= 8.0.2)
activerecord (= 8.0.2)
activesupport (= 8.0.2)
activestorage (8.0.0)
actionpack (= 8.0.0)
activejob (= 8.0.0)
activerecord (= 8.0.0)
activesupport (= 8.0.0)
marcel (~> 1.0)
activesupport (8.0.2)
activesupport (8.0.0)
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.3)
ast (2.4.2)
base64 (0.2.0)
bcrypt (3.1.20)
benchmark (0.4.0)
bigdecimal (3.1.9)
bigdecimal (3.1.8)
bindex (0.8.1)
bootsnap (1.18.6)
bootsnap (1.18.3)
msgpack (~> 1.2)
bootstrap_form (5.4.0)
actionpack (>= 6.1)
activemodel (>= 6.1)
brakeman (7.0.2)
brakeman (6.1.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.2.0)
caxlsx (4.1.0)
htmlentities (~> 4.3, >= 4.3.4)
marcel (~> 1.0)
nokogiri (~> 1.10, >= 1.10.4)
@ -105,57 +105,47 @@ GEM
caxlsx_rails (0.6.4)
actionpack (>= 3.1)
caxlsx (>= 3.0)
concurrent-ruby (1.3.5)
connection_pool (2.5.3)
concurrent-ruby (1.3.3)
connection_pool (2.4.1)
crass (1.0.6)
cssbundling-rails (1.4.3)
cssbundling-rails (1.4.0)
railties (>= 6.0.0)
date (3.4.1)
debug (1.10.0)
date (3.4.0)
debug (1.9.2)
irb (~> 1.10)
reline (>= 0.3.8)
deepl-rb (3.2.0)
drb (2.2.1)
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)
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)
globalid (1.2.1)
activesupport (>= 6.1)
hpricot (0.8.6)
html2slim (0.2.0)
hpricot
htmlentities (4.3.4)
i18n (1.14.7)
i18n (1.14.5)
concurrent-ruby (~> 1.0)
image_processing (1.14.0)
mini_magick (>= 4.9.5, < 6)
image_processing (1.12.2)
mini_magick (>= 4.9.5, < 5)
ruby-vips (>= 2.0.17, < 3)
io-console (0.8.0)
irb (1.15.2)
pp (>= 0.6.0)
io-console (0.7.2)
irb (1.14.0)
rdoc (>= 4.0.0)
reline (>= 0.4.2)
jbuilder (2.13.0)
jbuilder (2.12.0)
actionview (>= 5.0.0)
activesupport (>= 5.0.0)
jsbundling-rails (1.3.1)
jsbundling-rails (1.3.0)
railties (>= 6.0.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)
json (2.7.2)
language_server-protocol (3.17.0.3)
logger (1.6.1)
loofah (2.22.0)
crass (~> 1.0.2)
nokogiri (>= 1.12.0)
mail (2.8.1)
@ -165,37 +155,31 @@ GEM
net-smtp
marcel (1.0.4)
matrix (0.4.2)
mini_magick (5.2.0)
benchmark
logger
mini_magick (4.13.2)
mini_mime (1.1.5)
minitest (5.25.5)
msgpack (1.8.0)
net-imap (0.5.8)
minitest (5.24.1)
msgpack (1.7.2)
net-imap (0.5.0)
date
net-protocol
net-pop (0.1.2)
net-protocol
net-protocol (0.2.2)
timeout
net-smtp (0.5.1)
net-smtp (0.5.0)
net-protocol
nio4r (2.7.4)
nokogiri (1.18.8-aarch64-linux-gnu)
nio4r (2.7.3)
nokogiri (1.16.6-aarch64-linux)
racc (~> 1.4)
nokogiri (1.18.8-aarch64-linux-musl)
nokogiri (1.16.6-arm-linux)
racc (~> 1.4)
nokogiri (1.18.8-arm-linux-gnu)
nokogiri (1.16.6-arm64-darwin)
racc (~> 1.4)
nokogiri (1.18.8-arm-linux-musl)
nokogiri (1.16.6-x86-linux)
racc (~> 1.4)
nokogiri (1.18.8-arm64-darwin)
nokogiri (1.16.6-x86_64-darwin)
racc (~> 1.4)
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)
nokogiri (1.16.6-x86_64-linux)
racc (~> 1.4)
openxml-docx (0.11.5)
nokogiri
@ -205,83 +189,76 @@ GEM
openxml-drawingml (0.3.1)
nokogiri
openxml-package (~> 0.3.2)
openxml-package (0.3.5)
openxml-package (0.3.4)
nokogiri
ox
rubyzip (~> 2.3)
ox (2.14.22)
bigdecimal (>= 3.0)
pagy (9.3.4)
rubyzip
ox (2.14.18)
pagy (9.0.2)
pandoc-ruby (2.1.10)
parallel (1.27.0)
parser (3.3.8.0)
parallel (1.25.1)
parser (3.3.4.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.1.0)
prawn-markup (1.0.0)
nokogiri
prawn
prawn-table
prawn-rails (1.6.0)
prawn-rails (1.4.2)
actionview (>= 3.1.0)
activesupport (>= 3.1.0)
prawn
prawn-table
prawn-table (0.2.2)
prawn (>= 1.3.0, < 3.0.0)
prettyprint (0.2.0)
prism (1.4.0)
prism (1.2.0)
propshaft (1.1.0)
actionpack (>= 7.0.0)
activesupport (>= 7.0.0)
rack
railties (>= 7.0.0)
psych (5.2.6)
date
psych (5.1.2)
stringio
public_suffix (6.0.2)
puma (6.6.0)
public_suffix (6.0.0)
puma (6.4.2)
nio4r (~> 2.0)
raabro (1.4.0)
racc (1.8.1)
rack (3.1.14)
rack-session (2.1.1)
base64 (>= 0.1.0)
racc (1.8.0)
rack (3.1.7)
rack-session (2.0.0)
rack (>= 3.0.0)
rack-test (2.2.0)
rack-test (2.1.0)
rack (>= 1.3)
rackup (2.2.1)
rackup (2.1.0)
rack (>= 3)
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)
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)
bundler (>= 1.15.0)
railties (= 8.0.2)
railties (= 8.0.0)
rails-dom-testing (2.2.0)
activesupport (>= 5.0.0)
minitest
nokogiri (>= 1.6)
rails-html-sanitizer (1.6.2)
rails-html-sanitizer (1.6.0)
loofah (~> 2.21)
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)
nokogiri (~> 1.14)
railties (8.0.0)
actionpack (= 8.0.0)
activesupport (= 8.0.0)
irb (~> 1.13)
rackup (>= 1.0.0)
rake (>= 12.2)
@ -289,62 +266,62 @@ GEM
zeitwerk (~> 2.6)
rainbow (3.1.1)
rake (13.2.1)
rbs (3.9.4)
rbs (3.6.1)
logger
rdoc (6.13.1)
rdoc (6.7.0)
psych (>= 4.0.0)
regexp_parser (2.10.0)
reline (0.6.1)
regexp_parser (2.9.2)
reline (0.5.9)
io-console (~> 0.5)
rexml (3.4.1)
rubocop (1.75.6)
rexml (3.3.2)
strscan
rubocop (1.65.0)
json (~> 2.3)
language_server-protocol (~> 3.17.0.2)
lint_roller (~> 1.1.0)
language_server-protocol (>= 3.17.0)
parallel (~> 1.10)
parser (>= 3.3.0.2)
rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 2.9.3, < 3.0)
rubocop-ast (>= 1.44.0, < 2.0)
regexp_parser (>= 2.4, < 3.0)
rexml (>= 3.2.5, < 4.0)
rubocop-ast (>= 1.31.1, < 2.0)
ruby-progressbar (~> 1.7)
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)
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)
activesupport (>= 4.2.0)
lint_roller (~> 1.1)
rack (>= 1.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)
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)
language_server-protocol (~> 3.17.0)
prism (>= 1.2, < 2.0)
rbs (>= 3, < 4)
sorbet-runtime (>= 0.5.10782)
ruby-lsp-rails (0.4.3)
ruby-lsp (>= 0.23.18, < 0.24.0)
ruby-lsp-rails (0.3.21)
ruby-lsp (>= 0.20.0, < 0.21.0)
ruby-progressbar (1.13.0)
ruby-vips (2.2.3)
ruby-vips (2.2.1)
ffi (~> 1.12)
logger
rubyzip (2.4.1)
rubyzip (2.3.2)
sablon (0.4.1)
nokogiri (>= 1.8.5)
rubyzip (>= 1.3.0)
securerandom (0.4.1)
selenium-webdriver (4.32.0)
securerandom (0.3.1)
selenium-webdriver (4.23.0)
base64 (~> 0.2)
logger (~> 1.4)
rexml (~> 3.2, >= 3.2.5)
@ -353,64 +330,53 @@ GEM
slim (5.2.1)
temple (~> 0.10.0)
tilt (>= 2.1.0)
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)
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)
railties (>= 6.0.0)
stringio (3.1.7)
stringio (3.1.1)
strscan (3.1.0)
temple (0.10.3)
thor (1.3.2)
tilt (2.6.0)
timeout (0.4.3)
thor (1.3.1)
tilt (2.4.0)
timeout (0.4.1)
ttfunk (1.8.0)
bigdecimal (~> 3.1)
turbo-rails (2.0.13)
actionpack (>= 7.1.0)
railties (>= 7.1.0)
turbo-rails (2.0.5)
actionpack (>= 6.0.0)
activejob (>= 6.0.0)
railties (>= 6.0.0)
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
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)
unicode-display_width (2.5.0)
uri (1.0.1)
useragent (0.16.10)
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.7)
base64
websocket-driver (0.7.6)
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.5)
xpath (3.2.0)
nokogiri (~> 1.8)
zeitwerk (2.7.2)
zeitwerk (2.6.16)
PLATFORMS
aarch64-linux-gnu
aarch64-linux-musl
arm-linux-gnu
arm-linux-musl
aarch64-linux
arm-linux
arm64-darwin
x86-linux
x86_64-darwin
x86_64-linux-gnu
x86_64-linux-musl
x86_64-linux
DEPENDENCIES
bcrypt (~> 3.1.7)
@ -422,7 +388,6 @@ DEPENDENCIES
caxlsx_rails
cssbundling-rails
debug
deepl-rb
html2slim
image_processing (~> 1.2)
jbuilder
@ -444,12 +409,14 @@ 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.6.2
2.5.15

View file

@ -1,3 +1,3 @@
web: RUBY_DEBUG_OPEN=true bin/rails server -b 0
js: yarn build --watch=forever
web: env RUBY_DEBUG_OPEN=true bin/rails server -b 0
js: yarn build --watch
css: yarn watch:css

View file

@ -2,7 +2,3 @@
`rails new -n a11yist -d sqlite3 --skip-action-mailbox --css bootstrap --js esbuild .`
## Installation
To [install](readme)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

View file

@ -28,8 +28,13 @@ $enable-rounded: false;
@import 'bootstrap/scss/bootstrap';
$lg-path-images: "";
$bootstrap-icons-font-dir: "";
@font-face {
font-display: block;
font-family: "bootstrap-icons";
src: url("./bootstrap-icons.woff2") format("woff2"),
url("./bootstrap-icons.woff") format("woff");
}
@import 'bootstrap-icons/font/bootstrap-icons';
@ -47,10 +52,6 @@ $bootstrap-icons-font-dir: "";
@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 +165,3 @@ trix-toolbar .trix-dialog--link {
} */
@import "./layout";
@import "./dropdown";

View file

@ -1,67 +0,0 @@
.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;
}
}

View file

@ -20,6 +20,37 @@ $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);
}
@ -60,10 +91,7 @@ $tertiary-dark-active-open: $gray-600;
.page_nav nav ul {
padding-left: 0;
list-style-type: none;
li {
margin-bottom: 0.5rem;
}
line-height: 2rem;
a {
color: var(--bs-text);
@ -195,15 +223,7 @@ 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;
@ -219,7 +239,6 @@ details.success_criterion {
>.content {
padding-left: 1rem;
padding-right: 1rem;
padding-bottom: 1rem;
}
}
@ -234,36 +253,26 @@ 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 {
border-left: solid 1px $tertiary-dark;
border-right: solid 1px $tertiary-dark;
border-top: solid 1px $tertiary-dark;
}
details.success_criterion:last-child {
border-bottom: solid 1px $tertiary-dark;
}
details.success_criterion[open] {
/* border: solid 1px $tertiary-dark; */
border: solid 1px $tertiary-dark;
>summary {
summary {
background-color: $tertiary-dark;
}
>summary:hover {
summary:hover {
background-color: $tertiary-dark-active-open;
}
}
@ -318,64 +327,3 @@ 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%);
}
}

View file

@ -22,9 +22,9 @@ class ApplicationController < ActionController::Base
path: :root
},
{
label: Project.model_name.human(count: 2),
icon: :'folder',
path: :projects },
label: Report.model_name.human(count: 2),
icon: :'journal-text',
path: :reports },
{
label: I18n.t("backoffice"),
icon: :gear,
@ -32,8 +32,7 @@ class ApplicationController < ActionController::Base
active: %w[backoffice checklists checks links link_categories].include?(controller_name) },
{
label: "Konto",
path: profile_path,
icon: "person-circle"
path: profile_path
}
]
else
@ -51,8 +50,4 @@ 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

View file

@ -81,7 +81,7 @@ class ChecksController < ApplicationController
# Only allow a list of trusted parameters through.
def check_params
params.require(:check).permit(:guideline_id,
params.require(:check).permit(:principle_id,
:number,
:name_de,
:name_en,
@ -95,9 +95,7 @@ class ChecksController < ApplicationController
:applicable_to_analogue,
:applicable_to_document,
:applicable_to_non_web,
:external_number_1,
:external_number_2,
:external_number_3,
:external_number,
:external_url,
:conformity_level,
:conformity_notice_de,

View file

@ -21,6 +21,7 @@ module Authentication
resume_session || request_authentication
end
def resume_session
Current.session ||= find_session_by_cookie
end
@ -29,6 +30,7 @@ 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
@ -38,6 +40,7 @@ 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

View file

@ -5,7 +5,6 @@ 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 } ]

View file

@ -19,9 +19,7 @@ class ElementsController < ApplicationController
end
# GET /elements/1/edit
def edit
render_modal
end
def edit; end
# POST /elements
def create
@ -89,6 +87,6 @@ class ElementsController < ApplicationController
# Only allow a list of trusted parameters through.
def element_params
params.require(:element).permit(:page_id, :title, :description, :position, :screenshot)
params.require(:element).permit(:page_id, :title, :description, :position)
end
end

View file

@ -1,58 +0,0 @@
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

View file

@ -20,6 +20,11 @@ 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",

View file

@ -19,7 +19,6 @@ class PagesController < ApplicationController
# GET /pages/1/edit
def edit
render_modal
end
# POST /pages

View file

@ -1,62 +0,0 @@
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

View file

@ -1,12 +1,11 @@
# 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 = @project.reports
@reports = Report.all
end
# GET /reports/1
@ -86,7 +85,7 @@ class ReportsController < ApplicationController
# GET /reports/new
def new
@report = Report.new(project_id: @project.id)
@report = Report.new
end
# GET /reports/1/edit
@ -94,45 +93,10 @@ class ReportsController < ApplicationController
# POST /reports
def create
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
@report = Report.new(report_params)
if success
redirect_to @report.reload, notice: "Report was successfully created."
if @report.save
redirect_to @report, notice: "Report was successfully created."
else
render :new, status: :unprocessable_entity
end
@ -150,7 +114,7 @@ class ReportsController < ApplicationController
# DELETE /reports/1
def destroy
@report.destroy!
redirect_to project_url(@report.project), notice: "Report was successfully destroyed.", status: :see_other
redirect_to reports_url, notice: "Report was successfully destroyed.", status: :see_other
end
def work
@ -166,7 +130,7 @@ class ReportsController < ApplicationController
# Only allow a list of trusted parameters through.
def report_params
params.require(:report).permit(:name, :comment, :url, :project_id)
params.require(:report).permit(:name, :comment, :url)
end
def filename(report, extension: "html")
@ -176,8 +140,4 @@ class ReportsController < ApplicationController
def page_param
params[:page_id]
end
def set_project
@project = Project.find(params[:project_id])
end
end

View file

@ -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 edit_comment]
before_action :set_success_criterion, only: %i[show edit update destroy]
# GET /success_criteria
def index
@ -18,9 +18,7 @@ class SuccessCriteriaController < ApplicationController
end
# GET /success_criteria/1/edit
def edit
render_modal()
end
def edit; end
# POST /success_criteria
def create
@ -108,10 +106,6 @@ class SuccessCriteriaController < ApplicationController
end
end
def edit_comment
render_modal()
end
private
# Use callbacks to share common setup or constraints between actions.

View file

@ -20,7 +20,7 @@ module ApplicationHelper
end
def safe_display(value, &block)
return if value.blank?
return unless value
yield(value)
end
@ -28,41 +28,4 @@ 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

View file

@ -1,19 +1,4 @@
# 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

View file

@ -1,27 +1,2 @@
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

View file

@ -1,2 +0,0 @@
module ProjectsHelper
end

View file

@ -25,21 +25,6 @@ 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)
path = if success_criterion.persisted?
@ -52,9 +37,9 @@ module SuccessCriteriaHelper
else
success_criterion.element
end
link_to tag.i(class: "bi bi-pencil") + " Bearbeiten".html_safe,
link_to tag.i(class: "bi bi-pencil"),
path,
class: "text-decoration-none xbtn xbtn-#{edit_mode ? 'link text-warning' : 'link text-body'}"
class: "btn btn-#{edit_mode ? 'link text-warning' : 'link text-body'}"
end
def success_criterion_badge(content, extra_classes: "")

View file

@ -1,6 +1,7 @@
// 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"

View file

@ -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.success_criterion").forEach(el => {
el.querySelectorAll("details").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.success_criterion").forEach(el => {
el.querySelectorAll("details").forEach(el => {
el.removeAttribute("open")
})
}

View file

@ -1,53 +0,0 @@
// 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()
}
}
}

View file

@ -1,16 +0,0 @@
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");
})
}
}

View file

@ -4,9 +4,6 @@
import { application } from "./application"
import Lightbox from '@stimulus-components/lightbox'
application.register('lightbox', Lightbox)
import AutosubmitController from "./autosubmit_controller"
application.register("autosubmit", AutosubmitController)
@ -22,15 +19,9 @@ 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)
@ -52,8 +43,5 @@ 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)

View file

@ -1,14 +0,0 @@
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()
}
}
}

View file

@ -1,7 +1,7 @@
# frozen_string_literal: true
class Check < ApplicationRecord
belongs_to :guideline
belongs_to :principle
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: { scope: :guideline_id }, presence: true
validates :number, uniqueness: true, 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,20 +129,4 @@ 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

View file

@ -11,12 +11,6 @@ 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.

View file

@ -1,18 +0,0 @@
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

View file

@ -2,7 +2,7 @@
module PdfDocuments
class Base
attr_reader :params, :font
attr_reader :params
def initialize(prawn_document, **params)
@prawn_document = prawn_document
@ -13,8 +13,7 @@ module PdfDocuments
# exta_bold: 'vendor/assets/fonts/Lexend-ExtraBold.ttf',
# italic: 'vendor/assets/fonts/Lexend-Regular.ttf'
# })
@font = "Helvetica"
@prawn_document.font @font, size: 12
@prawn_document.font "Helvetica", size: 12
@params = OpenStruct.new(params)
end
@ -41,12 +40,8 @@ module PdfDocuments
@prawn_document.markup "<h3>#{text}</h3>"
end
def heading4(text)
@prawn_document.markup "<h4>#{text}</h4>"
end
def text(text, **args)
@prawn_document.text text, markup_options[:text].merge(args)
def text(text)
@prawn_document.text text, markup_options[:text]
end
def rich_text(text)
@ -60,28 +55,28 @@ module PdfDocuments
def markup_options
{
text: { size: 12, margin_bottom: 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 }
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 }
}
end
def logo(width: 24, xs: true)
@prawn_document.image "app/assets/images/logo-apfelschule#{ xs ? "_xs" : "" }.png", width:
def logo
@prawn_document.image "app/assets/images/logo-apfelschule.png", width: 150
@prawn_document.move_down 30
end
def prepare_rich_text(rich_text)
{ h1: "h5" }.each do |tag, replacement|
{ h1: "h4" }.each do |tag, replacement|
rich_text = rich_text.to_s.gsub("<#{tag}", "<#{replacement}")
rich_text = rich_text.to_s.gsub("</#{tag}>", "</#{replacement}>")
end
rich_text.sub(/(<br>)+$/, "")
rich_text
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(...)
@ -94,58 +89,5 @@ 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

View file

@ -5,163 +5,26 @@ module PdfDocuments
private
def generate
move_down 130
logo(width: 250, xs: false)
move_down 40
heading1 params.report.name
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
@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("<b>Pfad:</b> #{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("<b>#{options[:label]}</b>", inline_format: true)
if options[:rich]
rich_text(_1)
else
text(_1)
end
end
end
if check.links.any?
move_down 5
text("<b>Links</b>", inline_format: true)
move_down 5
check.links.group_by(&:link_category).each do |cat, links|
rich_text(%Q(
<span>#{cat.name}</span>
<ul>
#{links.map { "<li><a href='#{_1.url}'>#{_1.text}</a></li>" }.join() }
</ul>
))
end
end
text("<b>Erfolgskriterien</b>", inline_format: true)
text criteria.map(&:number).sort.join(", ")
end
string = "Seite <page> / <total>"
# 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 "<b>#{params.report.name}</b>", 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
@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
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
heading1 params.report.name
rich_text params.report.comment
private
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
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
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
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("<link href='#{_1}'>#{success_criterion.check.external_number || _1}</link>", inline_format: true)
end
move_down(10)
end
end
end

View file

@ -1,7 +0,0 @@
class Project < ApplicationRecord
has_many :reports, dependent: :restrict_with_error
has_rich_text :details
scope :current, -> { where("updated_at > ?", 1.month.ago) }
end

View file

@ -1,28 +1,9 @@
# 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

View file

@ -17,10 +17,6 @@ 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

View file

@ -7,12 +7,6 @@
<%= link_to Checklist.model_name.human(count: Checklist.count), :checklists %>
</p>
<p>
<i class="bi bi-rulers"></i>
<%= Guideline.count %>
<%= link_to Guideline.model_name.human(count: Guideline.count), :guidelines %>
</p>
<p>
<i class="bi bi-check2"></i>
<%= Check.count %>

View file

@ -1,2 +1 @@
<%= turbo_stream.remove dom_id(@checklist_entry) %>
<%= turbo_stream_toast("Check wurde aus Checkliste entfernt", true) %>

View file

@ -11,8 +11,8 @@ div id=dom_id(check)
th = Check.human_attribute_name(:number)
td = check.number
tr
th = Guideline.model_name.human
td = check.guideline&.name_en
th = Principle.model_name.human
td = check.principle&.t_name
tr
th = Standard.model_name.human(count: check.standard_ids.size)
td = check.standards.map(&:t_name).sort_by(&:downcase).join(", ")

View file

@ -1,9 +1,9 @@
= bootstrap_form_with(model: check, remote: true, data: { controller: "unsaved-changes" }) do |form|
h2 Details
= multilang_form_field(form, :name)
.row
= 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
.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_check_boxes :standard_ids, Standard.all.sort_by{ _1.t_name.downcase }, :id, :t_name, include_blank: true
h2 Einschränkung/Zugänglichkeit

View file

@ -1,6 +1,6 @@
<div id="<%= dom_id element %>" class="mb-5">
<%= turbo_frame_tag dom_id(element, :frame) do %>
<div class="d-flex border-bottom mb-3">
<div class="d-flex">
<h3 class="h4">
<i class="bi bi-boxes">
</i>
@ -9,23 +9,22 @@
<%= element.title %>
</span>
</h3>
<%= element_menu(element) %>
<%= link_to [:edit, element], class: "btn btn-link text-secondary" do %>
<i class="bi bi-pencil">
</i>
<% end %>
<%= button_to(element_path(element), method: :delete, class: "btn btn-link text-danger", data: { turbo_confirm: "Bist du sicher?"}) do %>
<i class="bi bi-trash"></i>
<% end %>
</div>
<div class="d-flex flex-column flex-sm-row">
<% if element.description %>
<div class="mb-3 flex-fill">
<div class="mb-3">
<%= element.description %>
</div>
<% end %>
<% safe_display(element.screenshot) do |s| %>
<div class="mb-3" data-controller="lightbox">
<%= link_to(s) do %>
<%= image_tag(s.variant(:thumbnail), class: "img-fluid", alt: "Screenshot des getesteten Elements") %>
<% end rescue nil %>
</div>
<% end %>
</div>
<p class="actions">
</p>
<% end %>
<div id="<%= dom_id(element, :success_criteria_list) %>" class="mb-3" data-controller="sortable" data-form-name="success_criterion" data-position-attribute= "position" data-draggable-selector=".draggable">

View file

@ -7,9 +7,6 @@
</div>
<%= element.description_html %>
<%= image_tag(element.screenshot.preview(:thumbnail)) %>
<%= image_tag(element.screenshot) %>
<% element.success_criteria.each do |sc| %>
<%= render sc %>
<% end %>

View file

@ -0,0 +1,7 @@
<%= 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 %>

View file

@ -1,10 +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.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")

View file

@ -1,7 +1,13 @@
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))
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
=< 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
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

View file

@ -1,6 +1,3 @@
= 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 }
= turbo_stream_toast("Element hinzugefügt", false)

View file

@ -3,6 +3,3 @@
- @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 }
= turbo_stream_toast("Element wurde gelöscht", true)

View file

@ -1,17 +1,19 @@
<h1><%= t("scaffold.pagetitle_edit", model: Element.model_name.human) %></h1>
<%= turbo_frame_tag dom_id(@element, :frame) do %>
<div>
<div class="d-flex">
<h2 class="h3">
<i class="bi bi-boxes">
</i>
<%= @element.title %>
<%= link_to(tag.i(class: "bi bi-pencil"), @element, class: "btn btn-link text-warning") %>
</div>
<%= render "form", element: @element %>
</div>
<% unless modal? %>
<div class="action-row">
<% end %>
<div class="action-row">
<%= 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) %>
</div>
<% end %>
</div>

View file

@ -5,7 +5,3 @@
/ = 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}"
= turbo_stream.replace dom_id(element, :frame), element
= turbo_stream_toast("Element gespeichert", false)

View file

@ -1,99 +1,55 @@
h1.title id=dom_id(@report) = @report.name
h1 id=dom_id(@report) = @report.name
h2 1 Einschätzung
p Gibt es hier Text?
h3 1.1 Zielsetzung und Ausgangslage
p Woher kommt dieser Text?
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|
- 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
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|
- 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
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 Testbericht
- @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}"
- if sc.test_comment?
p = sc.test_comment
- 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)
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)
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)
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
.body_text = scs.map(&:number).join(", ")
p = scs.map(&:number).join(", ")

View file

@ -1,7 +0,0 @@
<%= 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 %>

View file

@ -1,15 +0,0 @@
<div id="<%= dom_id guideline %>">
<p>
<strong>Principle:</strong>
<%= guideline.principle.t_name %>
</p>
<%= guideline.description_de %>
<h2 class="mt-4">Richtlinien</h2>
<% guideline.checks.each do |check| %>
<section class="pt-3">
<h3 class="fs-5"><%= link_to check %></h3>
<%= check.t_criterion %>
</section>
<% end %>
</div>

View file

@ -1,2 +0,0 @@
json.extract! guideline, :id, :principle_id, :number, :name_de, :created_at, :updated_at
json.url guideline_url(guideline, format: :json)

View file

@ -1,8 +0,0 @@
<h1><%= t("scaffold.pagetitle_edit", model: Guideline.model_name.human) %></h1>
<%= render "form", guideline: @guideline %>
<div class="action-row">
<%= 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 %>
</div>

View file

@ -1,28 +0,0 @@
<h1><%= t("scaffold.pagetitle_index", model: Guideline.model_name.human(count: 2)) %></h1>
<table class="table table-striped">
<thead>
<tr>
<th><%= Guideline.human_attribute_name(:name_de) %></th>
<th><%= Guideline.human_attribute_name(:description_de) %></th>
</thead>
<tbody>
<% @guidelines.each do |guideline| %>
<tr>
<td><%= link_to(guideline, url_for(guideline)) %></td>
<td><%= link_to(guideline.description_de, url_for(guideline)) %></td>
</tr>
<% end %>
</tbody>
</table>
<div class="action-row">
<%= link_to t("scaffold.link_new", model: Guideline.model_name.human), new_guideline_path %>
</div>

View file

@ -1 +0,0 @@
json.array! @guidelines, partial: "guidelines/guideline", as: :guideline

View file

@ -1,7 +0,0 @@
<h1><%= t("scaffold.pagetitle_new", model: Guideline.model_name.human) %></h1>
<%= render "form", guideline: @guideline %>
<div class="action-row">
<%= link_to t("scaffold.link_index", model: Guideline.model_name.human(count: 2)), guidelines_path %>
</div>

View file

@ -1,9 +0,0 @@
<h1><%= @guideline %></h1>
<%= render @guideline %>
<div class="action-row">
<%= 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" %>
</div>

View file

@ -1 +0,0 @@
json.partial! "guidelines/guideline", guideline: @guideline

View file

@ -1,33 +1,20 @@
h1 Dashboard
h1 a11ydive
h2 Dashboard
.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)
- if Report.any?
h2
i.bi.bi-journal-text>
'Zuletzt bearbeitete Prüfberichte
- 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)
.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"
p
i.bi.bi-journal-text
=< Report.count
=< link_to Report.model_name.human(count: Report.count), :reports
h2 Hotkeys
p Auf der Bericht-Ausfüllen Seite können folgende Shortcuts verwendet werden:
dl
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

View file

@ -1,8 +0,0 @@
.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

View file

@ -1,5 +1,5 @@
doctype html
html lang=:de data-bs-theme="#{cookies[:"modeTheme"] || "light"}" data-controller="set-theme"
html data-bs-theme="#{cookies[:"modeTheme"] || "light"}" data-controller="set-theme"
head
title a11ydive
meta[name="viewport" content="width=device-width,initial-scale=1"]
@ -16,11 +16,5 @@ html lang=:de data-bs-theme="#{cookies[:"modeTheme"] || "light"}" data-controlle
main.col.ps-md-2.pt-2
#main-content[data-controller="rich-text-link-targets"]
= yield
.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"
/footer.container-fluid.mt-auto.border-top
= Rails.configuration.build_version && "Version: #{Rails.configuration.build_version}"

View file

@ -1,10 +1,12 @@
doctype html
html
html data-bs-theme="light" data-controller="set-theme"
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.container#main-content
main#main-content
= yield

View file

@ -1,9 +0,0 @@
= 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"

View file

@ -2,5 +2,4 @@
= form.text_field :path
= form.text_field :url
= form.submit
- unless modal?
= link_to("Abbrechen", report_path(@page.report), class: "btn btn-outline-secondary")

View file

@ -11,5 +11,5 @@
<% end %>
</div>
<%= 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 %>
<%= 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 %>
</div>

View file

@ -2,9 +2,7 @@
<%= render "form", page: @page %>
<% unless modal? %>
<div class="action-row">
<%= 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) %>
</div>
<% end %>

View file

@ -11,8 +11,7 @@ h2
= turbo_frame_tag(dom_id(@page, :notes)) do
= render partial: "pages/notes", locals: { page: @page }
- unless modal?
.action-row
.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"

View file

@ -5,5 +5,3 @@
= 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}"
= turbo_stream_toast("Pfad gespeichert", false)

View file

@ -1,5 +0,0 @@
<%= bootstrap_form_with(model: project) do |form| %>
<%= form.text_field :name %>
<%= form.rich_text_area :details %>
<%= form.submit %>
<% end %>

View file

@ -1,20 +0,0 @@
.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

View file

@ -1,2 +0,0 @@
json.extract! project, :id, :name, :created_at, :updated_at
json.url project_url(project, format: :json)

View file

@ -1,8 +0,0 @@
<h1><%= t("scaffold.pagetitle_edit", model: Project.model_name.human) %></h1>
<%= render "form", project: @project %>
<div class="action-row">
<%= 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 %>
</div>

View file

@ -1,25 +0,0 @@
<h1><%= t("scaffold.pagetitle_index", model: Project.model_name.human(count: 2)) %></h1>
<table class="table table-striped">
<thead>
<tr>
<th><%= Project.human_attribute_name(:id) %></th>
<th><%= Project.human_attribute_name(:name) %></th>
</thead>
<tbody>
<% @projects.each do |project| %>
<tr>
<td><%= link_to(project.id, url_for(project)) %></td>
<td><%= link_to(project.name, url_for(project)) %></td>
</tr>
<% end %>
</tbody>
</table>
<div class="action-row">
<%= link_to t("scaffold.link_new", model: Project.model_name.human), new_project_path %>
</div>

View file

@ -1 +0,0 @@
json.array! @projects, partial: "projects/project", as: :project

View file

@ -1,7 +0,0 @@
<h1><%= t("scaffold.pagetitle_new", model: Project.model_name.human) %></h1>
<%= render "form", project: @project %>
<div class="action-row">
<%= link_to t("scaffold.link_index", model: Project.model_name.human(count: 2)), projects_path %>
</div>

View file

@ -1,9 +0,0 @@
<h1><%= t("scaffold.pagetitle_show", model: @project.class.model_name.human) %></h1>
<%= render @project %>
<div class="action-row">
<%= 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? %>
</div>

View file

@ -1 +0,0 @@
json.partial! "projects/project", project: @project

View file

@ -1,5 +1,4 @@
<%= bootstrap_form_with(model: report.persisted? ? report : [@project, report]) do |form| %>
<%= form.collection_select :project_id, Project.all, :id, :name, include_blank: true %>
<%= bootstrap_form_with(model: report) do |form| %>
<%= form.text_field :name %>
<%= form.text_field :url %>
<%= form.rich_text_area :comment %>

View file

@ -4,5 +4,5 @@
<div class="action-row">
<%= 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)), project_reports_path(@report.project) %>
<%= link_to t("scaffold.link_index", model: Report.model_name.human(count: 2)), reports_path %>
</div>

View file

@ -27,5 +27,5 @@
</table>
<div class="action-row">
<%= link_to t("scaffold.link_new", model: Report.model_name.human), new_project_report_path(@project) %>
<%= link_to t("scaffold.link_new", model: Report.model_name.human), new_report_path %>
</div>

View file

@ -3,5 +3,5 @@
<%= render "form", report: @report %>
<div class="action-row">
<%= link_to t("scaffold.link_index", model: Report.model_name.human(count: 2)), project_reports_path(@project) %>
<%= link_to t("scaffold.link_index", model: Report.model_name.human(count: 2)), reports_path %>
</div>

View file

@ -1,32 +1,29 @@
.border-bottom.mb-3
h1
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
div
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 @report.comment
.smb-4.lead.mb-3
= @report.comment
- if @current_page
.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
.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?" }})
.row
.col-lg-3.col-md-4.col-sm-12
.page_nav.sticky-top
@ -43,9 +40,9 @@ p
= 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
@ -63,5 +60,5 @@ p
| 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)), 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?"}
= 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"

View file

@ -1,6 +1,7 @@
.content id="#{dom_id(success_criterion, :body)}"
= turbo_frame_tag(dom_id(success_criterion, :frame)) do
.d-flex
.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)
@ -11,11 +12,8 @@
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)
= 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)
.row
.col
- if success_criterion.test_comment?
@ -47,7 +45,7 @@
.text-end.fw-bold = SuccessCriterion.human_attribute_name(:quick_fix)
.col-md-8.col-lg-9
= success_criterion.quick_fix
.row
.row.mb-3
.col-md-4.col-lg-3
.text-end.fw-bold = SuccessCriterion.human_attribute_name(:test_instructions)
.col-md-8.col-lg-9

View file

@ -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" %>
<%= link_to "Abbrechen", success_criterion.persisted? ? success_criterion : success_criterion.element, class: "btn btn-outline-secondary" %>
<% end %>

View file

@ -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"
- unless modal?
p Not MODAL
=< link_to "Abbrechen", success_criterion.persisted? ? success_criterion : success_criterion.element, class: "btn btn-outline-secondary"

View file

@ -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.py-1
.flex-fill
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.me-1
i.bi.bi-grip-vertical.handle

View file

@ -1,3 +0,0 @@
= 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?"})

View file

@ -2,5 +2,3 @@
- @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}"
= turbo_stream_toast("Erfolgskriterium wurde gelöscht", true)

View file

@ -0,0 +1,10 @@
<h1><%= t("scaffold.pagetitle_edit", model: SuccessCriterion.model_name.human) %></h1>
<%= turbo_frame_tag(dom_id(@success_criterion, :frame)) do %>
<%= render "form", success_criterion: @success_criterion %>
<% end %>
<div class="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) %>
</div>

View file

@ -1,7 +0,0 @@
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)

View file

@ -1,6 +0,0 @@
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"

View file

@ -3,4 +3,3 @@
- @success_criterion.element.success_criteria.each do |sc|
= turbo_stream.update(dom_id(sc, :position), sc.number)
= turbo_stream_toast("Erfolgskriterium gespeichert: #{t("activerecord.attributes.success_criterion.results/#{@success_criterion.result}")}", false)

Some files were not shown because too many files have changed in this diff Show more