Compare commits
149 Commits
2f3d64b5b9
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| b8fdc3f98a | |||
| a588f79b37 | |||
| 624b046db4 | |||
| b534e45792 | |||
| b5557670ba | |||
| a01ac2203e | |||
| e1c6a90830 | |||
| d856267e84 | |||
| b0666533ec | |||
| 0f03e4de59 | |||
| 3803d6657b | |||
| 25b40f99d5 | |||
| 350cc2dc78 | |||
| 88b5568b2f | |||
| 1dcac5b6f4 | |||
| 89b2763a7b | |||
| 6ce1b80360 | |||
| a2269cb6b9 | |||
| d28f9ce305 | |||
| b3c79e095b | |||
| def3fb7ee2 | |||
| c625d61c0d | |||
| 337ff9b9d9 | |||
| 23749c80b8 | |||
| 1fd6ba27d5 | |||
| 8e111dea0d | |||
| 5c7c079c22 | |||
| 4ed1cbb528 | |||
| e2cf5bb19e | |||
| 5237ab9af6 | |||
| f5eece52ee | |||
| 5b60eb64ad | |||
| de3aa07259 | |||
| d81d44ce9f | |||
| f7bf922f44 | |||
| 3b1a3ab27e | |||
| 4afcb818f3 | |||
| 2039f00896 | |||
| 40481faab8 | |||
| 3af0f6f563 | |||
| 0452c4538b | |||
| 82f91c7111 | |||
| 084613bbf5 | |||
| 0f877456a4 | |||
| feb37a8a6b | |||
| 87a91471d9 | |||
| fd30d51f17 | |||
| af8b91cf9c | |||
| 44169f2f96 | |||
| 5b6ff5ae90 | |||
| 84b92f54bf | |||
| 42c276b238 | |||
| b8b28d5a2a | |||
| f307ff9e68 | |||
| e5bd21823c | |||
| ff1c1017cf | |||
| 4bff15cd4e | |||
| c3c01bc736 | |||
| 873263be40 | |||
| a169b8fae8 | |||
| ace50699fb | |||
| bf87e09bc6 | |||
| 472236e6f5 | |||
| bd58c9d0c6 | |||
| 70dd3a0ab8 | |||
| ca59573581 | |||
| 03b1158e7a | |||
| 8bef03c2ce | |||
| cb1879055c | |||
| b5021d5683 | |||
| 7b6a2faeca | |||
| e7af7bae2f | |||
| 848777481d | |||
| b1b24a3b26 | |||
| 47901de8a3 | |||
| e6cbeb9596 | |||
| 11d944b64c | |||
| d031245655 | |||
| e2b2d0d38b | |||
| 44981c58f8 | |||
| 606b500fd0 | |||
| e440fbe602 | |||
| 815a8bae4d | |||
| 216cad306c | |||
| 0116e94475 | |||
| 7144fea077 | |||
| affc7671c6 | |||
| 121674e379 | |||
| 8da2ffdf38 | |||
| b306148120 | |||
| 3924b8f6f6 | |||
| d6d8563af3 | |||
| 9cc7448d53 | |||
| 4db1c7667e | |||
| 5ee276e2eb | |||
| d294a3f7f0 | |||
| 418b41556e | |||
| 64289d045d | |||
| 74038c0615 | |||
| 1193eb57d2 | |||
| 6ae05c2c9d | |||
| 0f43113e88 | |||
| 3899048349 | |||
| 7d328368e9 | |||
| fadcea03c0 | |||
| aebadb3ae5 | |||
| 2814995ac7 | |||
| 8f4c0edb4c | |||
| f86c8553af | |||
| a3b7ff708c | |||
| 7aeefd52bf | |||
| 64116ed292 | |||
| c101bc395d | |||
| d3b085e87b | |||
| 1492fba3bb | |||
| c195cd3b22 | |||
| cf8cc196a3 | |||
| d4ffe510c9 | |||
| 0da6c0ff90 | |||
| a456f7fcb1 | |||
| beab461e6e | |||
| ba4331c252 | |||
| fc26bdc3ac | |||
| 6d1fbc5af4 | |||
| 26ccaa9bb4 | |||
| 68ced40cbf | |||
| a9005b69ff | |||
| 14cca34105 | |||
| 09fae0677d | |||
| 230a286eb8 | |||
| fbbf0b5aac | |||
| 6aca35ff46 | |||
| 76ea655e4f | |||
| 017d6d25ae | |||
| 4bbb5926b1 | |||
| adc40dbce2 | |||
| caeb2520c5 | |||
| ec4285f999 | |||
| 607b90dcc7 | |||
| 9275f29196 | |||
| fe9dbcfff0 | |||
| 18c343f9fb | |||
| a51ceeade5 | |||
| 8fb6c100e7 | |||
| 0953d5c915 | |||
| 7b7ba97032 | |||
| f4068c10bd | |||
| 4f3342a850 | |||
| 1195da6843 |
30
Gemfile
30
Gemfile
@@ -1,11 +1,11 @@
|
|||||||
source "https://rubygems.org"
|
source "https://rubygems.org"
|
||||||
|
|
||||||
# Bundle edge Rails instead: gem "rails", github: "rails/rails", branch: "main"
|
# Bundle edge Rails instead: gem "rails", github: "rails/rails", branch: "main"
|
||||||
gem "rails", "~> 7.2.0", ">= 7.2.0"
|
gem "rails", "~> 8.0.0"
|
||||||
# The original asset pipeline for Rails [https://github.com/rails/sprockets-rails]
|
# The original asset pipeline for Rails [https://github.com/rails/sprockets-rails]
|
||||||
gem "sprockets-rails"
|
gem "sprockets-rails"
|
||||||
# Use sqlite3 as the database for Active Record
|
# Use sqlite3 as the database for Active Record
|
||||||
gem "sqlite3", "~> 1.4"
|
gem "sqlite3", ">= 2.1"
|
||||||
# Use the Puma web server [https://github.com/puma/puma]
|
# Use the Puma web server [https://github.com/puma/puma]
|
||||||
gem "puma", ">= 5.0"
|
gem "puma", ">= 5.0"
|
||||||
# Use JavaScript with ESM import maps [https://github.com/rails/importmap-rails]
|
# Use JavaScript with ESM import maps [https://github.com/rails/importmap-rails]
|
||||||
@@ -15,7 +15,7 @@ gem "turbo-rails"
|
|||||||
# Hotwire's modest JavaScript framework [https://stimulus.hotwired.dev]
|
# Hotwire's modest JavaScript framework [https://stimulus.hotwired.dev]
|
||||||
gem "stimulus-rails"
|
gem "stimulus-rails"
|
||||||
# Use Tailwind CSS [https://github.com/rails/tailwindcss-rails]
|
# Use Tailwind CSS [https://github.com/rails/tailwindcss-rails]
|
||||||
gem "tailwindcss-rails"
|
gem "tailwindcss-rails", "~> 3.3.1"
|
||||||
# Build JSON APIs with ease [https://github.com/rails/jbuilder]
|
# Build JSON APIs with ease [https://github.com/rails/jbuilder]
|
||||||
gem "jbuilder"
|
gem "jbuilder"
|
||||||
# Use Redis adapter to run Action Cable in production
|
# Use Redis adapter to run Action Cable in production
|
||||||
@@ -30,9 +30,20 @@ gem "bcrypt", "~> 3.1.7"
|
|||||||
# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
|
# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
|
||||||
gem "tzinfo-data", platforms: %i[windows jruby]
|
gem "tzinfo-data", platforms: %i[windows jruby]
|
||||||
|
|
||||||
|
# Use the database-backed adapters for Rails.cache, Active Job, and Action Cable
|
||||||
|
gem "solid_cache"
|
||||||
|
gem "solid_queue"
|
||||||
|
gem "solid_cable"
|
||||||
|
|
||||||
# Reduces boot times through caching; required in config/boot.rb
|
# Reduces boot times through caching; required in config/boot.rb
|
||||||
gem "bootsnap", require: false
|
gem "bootsnap", require: false
|
||||||
|
|
||||||
|
# Deploy this application anywhere as a Docker container [https://kamal-deploy.org]
|
||||||
|
gem "kamal", require: false
|
||||||
|
|
||||||
|
# Add HTTP asset caching/compression and X-Sendfile acceleration to Puma [https://github.com/basecamp/thruster/]
|
||||||
|
gem "thruster", require: false
|
||||||
|
|
||||||
# Use Active Storage variants [https://guides.rubyonrails.org/active_storage_overview.html#transforming-images]
|
# Use Active Storage variants [https://guides.rubyonrails.org/active_storage_overview.html#transforming-images]
|
||||||
gem "image_processing", "~> 1.2"
|
gem "image_processing", "~> 1.2"
|
||||||
|
|
||||||
@@ -75,7 +86,20 @@ gem "inline_svg", "~> 1.9"
|
|||||||
# Used by pdf_analyzer for extracting pageformats
|
# Used by pdf_analyzer for extracting pageformats
|
||||||
gem "pdf-reader", "~> 2.12"
|
gem "pdf-reader", "~> 2.12"
|
||||||
|
|
||||||
|
# Authentication Scaffold
|
||||||
gem "authentication-zero", "~> 3.0"
|
gem "authentication-zero", "~> 3.0"
|
||||||
|
|
||||||
# Use Pwned to check if a password has been found in any of the huge data breaches [https://github.com/philnash/pwned]
|
# Use Pwned to check if a password has been found in any of the huge data breaches [https://github.com/philnash/pwned]
|
||||||
gem "pwned"
|
gem "pwned"
|
||||||
|
|
||||||
|
gem "action_policy", "~> 0.7.1"
|
||||||
|
|
||||||
|
gem "pagy", "~> 9.0"
|
||||||
|
|
||||||
|
gem "csv", "~> 3.3"
|
||||||
|
|
||||||
|
# Centralization of locale data collection for Ruby on Rails.
|
||||||
|
# URL: https://github.com/svenfuchs/rails-i18n
|
||||||
|
gem "rails-i18n", "~> 8.0"
|
||||||
|
|
||||||
|
gem "ransack", "~> 4.2"
|
||||||
|
|||||||
472
Gemfile.lock
472
Gemfile.lock
@@ -1,68 +1,70 @@
|
|||||||
GEM
|
GEM
|
||||||
remote: https://rubygems.org/
|
remote: https://rubygems.org/
|
||||||
specs:
|
specs:
|
||||||
Ascii85 (1.1.1)
|
Ascii85 (2.0.1)
|
||||||
actioncable (7.2.0)
|
action_policy (0.7.5)
|
||||||
actionpack (= 7.2.0)
|
ruby-next-core (>= 1.0)
|
||||||
activesupport (= 7.2.0)
|
actioncable (8.0.2.1)
|
||||||
|
actionpack (= 8.0.2.1)
|
||||||
|
activesupport (= 8.0.2.1)
|
||||||
nio4r (~> 2.0)
|
nio4r (~> 2.0)
|
||||||
websocket-driver (>= 0.6.1)
|
websocket-driver (>= 0.6.1)
|
||||||
zeitwerk (~> 2.6)
|
zeitwerk (~> 2.6)
|
||||||
actionmailbox (7.2.0)
|
actionmailbox (8.0.2.1)
|
||||||
actionpack (= 7.2.0)
|
actionpack (= 8.0.2.1)
|
||||||
activejob (= 7.2.0)
|
activejob (= 8.0.2.1)
|
||||||
activerecord (= 7.2.0)
|
activerecord (= 8.0.2.1)
|
||||||
activestorage (= 7.2.0)
|
activestorage (= 8.0.2.1)
|
||||||
activesupport (= 7.2.0)
|
activesupport (= 8.0.2.1)
|
||||||
mail (>= 2.8.0)
|
mail (>= 2.8.0)
|
||||||
actionmailer (7.2.0)
|
actionmailer (8.0.2.1)
|
||||||
actionpack (= 7.2.0)
|
actionpack (= 8.0.2.1)
|
||||||
actionview (= 7.2.0)
|
actionview (= 8.0.2.1)
|
||||||
activejob (= 7.2.0)
|
activejob (= 8.0.2.1)
|
||||||
activesupport (= 7.2.0)
|
activesupport (= 8.0.2.1)
|
||||||
mail (>= 2.8.0)
|
mail (>= 2.8.0)
|
||||||
rails-dom-testing (~> 2.2)
|
rails-dom-testing (~> 2.2)
|
||||||
actionpack (7.2.0)
|
actionpack (8.0.2.1)
|
||||||
actionview (= 7.2.0)
|
actionview (= 8.0.2.1)
|
||||||
activesupport (= 7.2.0)
|
activesupport (= 8.0.2.1)
|
||||||
nokogiri (>= 1.8.5)
|
nokogiri (>= 1.8.5)
|
||||||
racc
|
rack (>= 2.2.4)
|
||||||
rack (>= 2.2.4, < 3.2)
|
|
||||||
rack-session (>= 1.0.1)
|
rack-session (>= 1.0.1)
|
||||||
rack-test (>= 0.6.3)
|
rack-test (>= 0.6.3)
|
||||||
rails-dom-testing (~> 2.2)
|
rails-dom-testing (~> 2.2)
|
||||||
rails-html-sanitizer (~> 1.6)
|
rails-html-sanitizer (~> 1.6)
|
||||||
useragent (~> 0.16)
|
useragent (~> 0.16)
|
||||||
actiontext (7.2.0)
|
actiontext (8.0.2.1)
|
||||||
actionpack (= 7.2.0)
|
actionpack (= 8.0.2.1)
|
||||||
activerecord (= 7.2.0)
|
activerecord (= 8.0.2.1)
|
||||||
activestorage (= 7.2.0)
|
activestorage (= 8.0.2.1)
|
||||||
activesupport (= 7.2.0)
|
activesupport (= 8.0.2.1)
|
||||||
globalid (>= 0.6.0)
|
globalid (>= 0.6.0)
|
||||||
nokogiri (>= 1.8.5)
|
nokogiri (>= 1.8.5)
|
||||||
actionview (7.2.0)
|
actionview (8.0.2.1)
|
||||||
activesupport (= 7.2.0)
|
activesupport (= 8.0.2.1)
|
||||||
builder (~> 3.1)
|
builder (~> 3.1)
|
||||||
erubi (~> 1.11)
|
erubi (~> 1.11)
|
||||||
rails-dom-testing (~> 2.2)
|
rails-dom-testing (~> 2.2)
|
||||||
rails-html-sanitizer (~> 1.6)
|
rails-html-sanitizer (~> 1.6)
|
||||||
activejob (7.2.0)
|
activejob (8.0.2.1)
|
||||||
activesupport (= 7.2.0)
|
activesupport (= 8.0.2.1)
|
||||||
globalid (>= 0.3.6)
|
globalid (>= 0.3.6)
|
||||||
activemodel (7.2.0)
|
activemodel (8.0.2.1)
|
||||||
activesupport (= 7.2.0)
|
activesupport (= 8.0.2.1)
|
||||||
activerecord (7.2.0)
|
activerecord (8.0.2.1)
|
||||||
activemodel (= 7.2.0)
|
activemodel (= 8.0.2.1)
|
||||||
activesupport (= 7.2.0)
|
activesupport (= 8.0.2.1)
|
||||||
timeout (>= 0.4.0)
|
timeout (>= 0.4.0)
|
||||||
activestorage (7.2.0)
|
activestorage (8.0.2.1)
|
||||||
actionpack (= 7.2.0)
|
actionpack (= 8.0.2.1)
|
||||||
activejob (= 7.2.0)
|
activejob (= 8.0.2.1)
|
||||||
activerecord (= 7.2.0)
|
activerecord (= 8.0.2.1)
|
||||||
activesupport (= 7.2.0)
|
activesupport (= 8.0.2.1)
|
||||||
marcel (~> 1.0)
|
marcel (~> 1.0)
|
||||||
activesupport (7.2.0)
|
activesupport (8.0.2.1)
|
||||||
base64
|
base64
|
||||||
|
benchmark (>= 0.3)
|
||||||
bigdecimal
|
bigdecimal
|
||||||
concurrent-ruby (~> 1.0, >= 1.3.1)
|
concurrent-ruby (~> 1.0, >= 1.3.1)
|
||||||
connection_pool (>= 2.2.5)
|
connection_pool (>= 2.2.5)
|
||||||
@@ -72,18 +74,23 @@ GEM
|
|||||||
minitest (>= 5.1)
|
minitest (>= 5.1)
|
||||||
securerandom (>= 0.3)
|
securerandom (>= 0.3)
|
||||||
tzinfo (~> 2.0, >= 2.0.5)
|
tzinfo (~> 2.0, >= 2.0.5)
|
||||||
|
uri (>= 0.13.1)
|
||||||
addressable (2.8.7)
|
addressable (2.8.7)
|
||||||
public_suffix (>= 2.0.2, < 7.0)
|
public_suffix (>= 2.0.2, < 7.0)
|
||||||
afm (0.2.2)
|
afm (1.0.0)
|
||||||
ast (2.4.2)
|
ast (2.4.3)
|
||||||
authentication-zero (3.0.2)
|
authentication-zero (3.0.2)
|
||||||
base64 (0.2.0)
|
base64 (0.3.0)
|
||||||
bcrypt (3.1.20)
|
bcrypt (3.1.20)
|
||||||
bigdecimal (3.1.8)
|
bcrypt_pbkdf (1.1.1)
|
||||||
|
bcrypt_pbkdf (1.1.1-arm64-darwin)
|
||||||
|
bcrypt_pbkdf (1.1.1-x86_64-darwin)
|
||||||
|
benchmark (0.4.1)
|
||||||
|
bigdecimal (3.2.2)
|
||||||
bindex (0.8.1)
|
bindex (0.8.1)
|
||||||
bootsnap (1.18.4)
|
bootsnap (1.18.6)
|
||||||
msgpack (~> 1.2)
|
msgpack (~> 1.2)
|
||||||
brakeman (6.1.2)
|
brakeman (7.1.0)
|
||||||
racc
|
racc
|
||||||
builder (3.3.0)
|
builder (3.3.0)
|
||||||
capybara (3.40.0)
|
capybara (3.40.0)
|
||||||
@@ -97,58 +104,81 @@ GEM
|
|||||||
xpath (~> 3.2)
|
xpath (~> 3.2)
|
||||||
childprocess (5.1.0)
|
childprocess (5.1.0)
|
||||||
logger (~> 1.5)
|
logger (~> 1.5)
|
||||||
concurrent-ruby (1.3.3)
|
concurrent-ruby (1.3.5)
|
||||||
connection_pool (2.4.1)
|
connection_pool (2.5.3)
|
||||||
crass (1.0.6)
|
crass (1.0.6)
|
||||||
date (3.3.4)
|
csv (3.3.5)
|
||||||
debug (1.9.2)
|
date (3.4.1)
|
||||||
|
debug (1.11.0)
|
||||||
irb (~> 1.10)
|
irb (~> 1.10)
|
||||||
reline (>= 0.3.8)
|
reline (>= 0.3.8)
|
||||||
drb (2.2.1)
|
dotenv (3.1.8)
|
||||||
erubi (1.13.0)
|
drb (2.2.3)
|
||||||
faker (3.4.2)
|
ed25519 (1.4.0)
|
||||||
|
erb (5.0.2)
|
||||||
|
erubi (1.13.1)
|
||||||
|
et-orbi (1.3.0)
|
||||||
|
tzinfo
|
||||||
|
faker (3.5.2)
|
||||||
i18n (>= 1.8.11, < 2)
|
i18n (>= 1.8.11, < 2)
|
||||||
ffi (1.17.0-aarch64-linux-gnu)
|
ffi (1.17.2-aarch64-linux-gnu)
|
||||||
ffi (1.17.0-arm-linux-gnu)
|
ffi (1.17.2-arm-linux-gnu)
|
||||||
ffi (1.17.0-arm64-darwin)
|
ffi (1.17.2-arm64-darwin)
|
||||||
ffi (1.17.0-x86-linux-gnu)
|
ffi (1.17.2-x86-linux-gnu)
|
||||||
ffi (1.17.0-x86_64-darwin)
|
ffi (1.17.2-x86_64-darwin)
|
||||||
ffi (1.17.0-x86_64-linux-gnu)
|
ffi (1.17.2-x86_64-linux-gnu)
|
||||||
|
fugit (1.11.1)
|
||||||
|
et-orbi (~> 1, >= 1.2.11)
|
||||||
|
raabro (~> 1.4)
|
||||||
globalid (1.2.1)
|
globalid (1.2.1)
|
||||||
activesupport (>= 6.1)
|
activesupport (>= 6.1)
|
||||||
hashery (2.1.2)
|
hashery (2.1.2)
|
||||||
i18n (1.14.5)
|
i18n (1.14.7)
|
||||||
concurrent-ruby (~> 1.0)
|
concurrent-ruby (~> 1.0)
|
||||||
image_processing (1.13.0)
|
image_processing (1.14.0)
|
||||||
mini_magick (>= 4.9.5, < 5)
|
mini_magick (>= 4.9.5, < 6)
|
||||||
ruby-vips (>= 2.0.17, < 3)
|
ruby-vips (>= 2.0.17, < 3)
|
||||||
importmap-rails (2.0.1)
|
importmap-rails (2.2.2)
|
||||||
actionpack (>= 6.0.0)
|
actionpack (>= 6.0.0)
|
||||||
activesupport (>= 6.0.0)
|
activesupport (>= 6.0.0)
|
||||||
railties (>= 6.0.0)
|
railties (>= 6.0.0)
|
||||||
inline_svg (1.9.0)
|
inline_svg (1.10.0)
|
||||||
activesupport (>= 3.0)
|
activesupport (>= 3.0)
|
||||||
nokogiri (>= 1.6)
|
nokogiri (>= 1.6)
|
||||||
io-console (0.7.2)
|
io-console (0.8.1)
|
||||||
irb (1.14.0)
|
irb (1.15.2)
|
||||||
|
pp (>= 0.6.0)
|
||||||
rdoc (>= 4.0.0)
|
rdoc (>= 4.0.0)
|
||||||
reline (>= 0.4.2)
|
reline (>= 0.4.2)
|
||||||
jbuilder (2.12.0)
|
jbuilder (2.14.1)
|
||||||
actionview (>= 5.0.0)
|
actionview (>= 7.0.0)
|
||||||
activesupport (>= 5.0.0)
|
activesupport (>= 7.0.0)
|
||||||
json (2.7.2)
|
json (2.13.2)
|
||||||
kredis (1.7.0)
|
kamal (2.7.0)
|
||||||
|
activesupport (>= 7.0)
|
||||||
|
base64 (~> 0.2)
|
||||||
|
bcrypt_pbkdf (~> 1.0)
|
||||||
|
concurrent-ruby (~> 1.2)
|
||||||
|
dotenv (~> 3.1)
|
||||||
|
ed25519 (~> 1.4)
|
||||||
|
net-ssh (~> 7.3)
|
||||||
|
sshkit (>= 1.23.0, < 2.0)
|
||||||
|
thor (~> 1.3)
|
||||||
|
zeitwerk (>= 2.6.18, < 3.0)
|
||||||
|
kredis (1.8.0)
|
||||||
activemodel (>= 6.0.0)
|
activemodel (>= 6.0.0)
|
||||||
activesupport (>= 6.0.0)
|
activesupport (>= 6.0.0)
|
||||||
redis (>= 4.2, < 6)
|
redis (>= 4.2, < 6)
|
||||||
language_server-protocol (3.17.0.3)
|
language_server-protocol (3.17.0.5)
|
||||||
launchy (3.0.1)
|
launchy (3.1.1)
|
||||||
addressable (~> 2.8)
|
addressable (~> 2.8)
|
||||||
childprocess (~> 5.0)
|
childprocess (~> 5.0)
|
||||||
|
logger (~> 1.6)
|
||||||
letter_opener (1.10.0)
|
letter_opener (1.10.0)
|
||||||
launchy (>= 2.2, < 4)
|
launchy (>= 2.2, < 4)
|
||||||
logger (1.6.0)
|
lint_roller (1.1.0)
|
||||||
loofah (2.22.0)
|
logger (1.7.0)
|
||||||
|
loofah (2.24.1)
|
||||||
crass (~> 1.0.2)
|
crass (~> 1.0.2)
|
||||||
nokogiri (>= 1.12.0)
|
nokogiri (>= 1.12.0)
|
||||||
mail (2.8.1)
|
mail (2.8.1)
|
||||||
@@ -157,196 +187,246 @@ GEM
|
|||||||
net-pop
|
net-pop
|
||||||
net-smtp
|
net-smtp
|
||||||
marcel (1.0.4)
|
marcel (1.0.4)
|
||||||
matrix (0.4.2)
|
matrix (0.4.3)
|
||||||
mini_magick (4.13.2)
|
mini_magick (5.3.1)
|
||||||
|
logger
|
||||||
mini_mime (1.1.5)
|
mini_mime (1.1.5)
|
||||||
minitest (5.24.1)
|
mini_portile2 (2.8.9)
|
||||||
msgpack (1.7.2)
|
minitest (5.25.5)
|
||||||
net-imap (0.4.14)
|
msgpack (1.8.0)
|
||||||
|
net-imap (0.5.9)
|
||||||
date
|
date
|
||||||
net-protocol
|
net-protocol
|
||||||
net-pop (0.1.2)
|
net-pop (0.1.2)
|
||||||
net-protocol
|
net-protocol
|
||||||
net-protocol (0.2.2)
|
net-protocol (0.2.2)
|
||||||
timeout
|
timeout
|
||||||
net-smtp (0.5.0)
|
net-scp (4.1.0)
|
||||||
|
net-ssh (>= 2.6.5, < 8.0.0)
|
||||||
|
net-sftp (4.0.0)
|
||||||
|
net-ssh (>= 5.0.0, < 8.0.0)
|
||||||
|
net-smtp (0.5.1)
|
||||||
net-protocol
|
net-protocol
|
||||||
nio4r (2.7.3)
|
net-ssh (7.3.0)
|
||||||
nokogiri (1.16.7-aarch64-linux)
|
nio4r (2.7.4)
|
||||||
|
nokogiri (1.18.9)
|
||||||
|
mini_portile2 (~> 2.8.2)
|
||||||
racc (~> 1.4)
|
racc (~> 1.4)
|
||||||
nokogiri (1.16.7-arm-linux)
|
nokogiri (1.18.9-aarch64-linux-gnu)
|
||||||
racc (~> 1.4)
|
racc (~> 1.4)
|
||||||
nokogiri (1.16.7-arm64-darwin)
|
nokogiri (1.18.9-arm-linux-gnu)
|
||||||
racc (~> 1.4)
|
racc (~> 1.4)
|
||||||
nokogiri (1.16.7-x86-linux)
|
nokogiri (1.18.9-arm64-darwin)
|
||||||
racc (~> 1.4)
|
racc (~> 1.4)
|
||||||
nokogiri (1.16.7-x86_64-darwin)
|
nokogiri (1.18.9-x86_64-darwin)
|
||||||
racc (~> 1.4)
|
racc (~> 1.4)
|
||||||
nokogiri (1.16.7-x86_64-linux)
|
nokogiri (1.18.9-x86_64-linux-gnu)
|
||||||
racc (~> 1.4)
|
racc (~> 1.4)
|
||||||
parallel (1.26.1)
|
ostruct (0.6.3)
|
||||||
parser (3.3.4.2)
|
pagy (9.4.0)
|
||||||
|
parallel (1.27.0)
|
||||||
|
parser (3.3.9.0)
|
||||||
ast (~> 2.4.1)
|
ast (~> 2.4.1)
|
||||||
racc
|
racc
|
||||||
pdf-reader (2.12.0)
|
pdf-reader (2.15.0)
|
||||||
Ascii85 (~> 1.0)
|
Ascii85 (>= 1.0, < 3.0, != 2.0.0)
|
||||||
afm (~> 0.2.1)
|
afm (>= 0.2.1, < 2)
|
||||||
hashery (~> 2.0)
|
hashery (~> 2.0)
|
||||||
ruby-rc4
|
ruby-rc4
|
||||||
ttfunk
|
ttfunk
|
||||||
psych (5.1.2)
|
pp (0.6.2)
|
||||||
|
prettyprint
|
||||||
|
prettyprint (0.2.0)
|
||||||
|
prism (1.4.0)
|
||||||
|
psych (5.2.6)
|
||||||
|
date
|
||||||
stringio
|
stringio
|
||||||
public_suffix (6.0.1)
|
public_suffix (6.0.2)
|
||||||
puma (6.4.2)
|
puma (6.6.1)
|
||||||
nio4r (~> 2.0)
|
nio4r (~> 2.0)
|
||||||
pwned (2.4.1)
|
pwned (2.4.1)
|
||||||
|
raabro (1.4.0)
|
||||||
racc (1.8.1)
|
racc (1.8.1)
|
||||||
rack (3.1.7)
|
rack (3.2.0)
|
||||||
rack-session (2.0.0)
|
rack-session (2.1.1)
|
||||||
|
base64 (>= 0.1.0)
|
||||||
rack (>= 3.0.0)
|
rack (>= 3.0.0)
|
||||||
rack-test (2.1.0)
|
rack-test (2.2.0)
|
||||||
rack (>= 1.3)
|
rack (>= 1.3)
|
||||||
rackup (2.1.0)
|
rackup (2.2.1)
|
||||||
rack (>= 3)
|
rack (>= 3)
|
||||||
webrick (~> 1.8)
|
rails (8.0.2.1)
|
||||||
rails (7.2.0)
|
actioncable (= 8.0.2.1)
|
||||||
actioncable (= 7.2.0)
|
actionmailbox (= 8.0.2.1)
|
||||||
actionmailbox (= 7.2.0)
|
actionmailer (= 8.0.2.1)
|
||||||
actionmailer (= 7.2.0)
|
actionpack (= 8.0.2.1)
|
||||||
actionpack (= 7.2.0)
|
actiontext (= 8.0.2.1)
|
||||||
actiontext (= 7.2.0)
|
actionview (= 8.0.2.1)
|
||||||
actionview (= 7.2.0)
|
activejob (= 8.0.2.1)
|
||||||
activejob (= 7.2.0)
|
activemodel (= 8.0.2.1)
|
||||||
activemodel (= 7.2.0)
|
activerecord (= 8.0.2.1)
|
||||||
activerecord (= 7.2.0)
|
activestorage (= 8.0.2.1)
|
||||||
activestorage (= 7.2.0)
|
activesupport (= 8.0.2.1)
|
||||||
activesupport (= 7.2.0)
|
|
||||||
bundler (>= 1.15.0)
|
bundler (>= 1.15.0)
|
||||||
railties (= 7.2.0)
|
railties (= 8.0.2.1)
|
||||||
rails-dom-testing (2.2.0)
|
rails-dom-testing (2.3.0)
|
||||||
activesupport (>= 5.0.0)
|
activesupport (>= 5.0.0)
|
||||||
minitest
|
minitest
|
||||||
nokogiri (>= 1.6)
|
nokogiri (>= 1.6)
|
||||||
rails-html-sanitizer (1.6.0)
|
rails-html-sanitizer (1.6.2)
|
||||||
loofah (~> 2.21)
|
loofah (~> 2.21)
|
||||||
nokogiri (~> 1.14)
|
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 (7.2.0)
|
rails-i18n (8.0.2)
|
||||||
actionpack (= 7.2.0)
|
i18n (>= 0.7, < 2)
|
||||||
activesupport (= 7.2.0)
|
railties (>= 8.0.0, < 9)
|
||||||
|
railties (8.0.2.1)
|
||||||
|
actionpack (= 8.0.2.1)
|
||||||
|
activesupport (= 8.0.2.1)
|
||||||
irb (~> 1.13)
|
irb (~> 1.13)
|
||||||
rackup (>= 1.0.0)
|
rackup (>= 1.0.0)
|
||||||
rake (>= 12.2)
|
rake (>= 12.2)
|
||||||
thor (~> 1.0, >= 1.2.2)
|
thor (~> 1.0, >= 1.2.2)
|
||||||
zeitwerk (~> 2.6)
|
zeitwerk (~> 2.6)
|
||||||
rainbow (3.1.1)
|
rainbow (3.1.1)
|
||||||
rake (13.2.1)
|
rake (13.3.0)
|
||||||
rdoc (6.7.0)
|
ransack (4.3.0)
|
||||||
|
activerecord (>= 6.1.5)
|
||||||
|
activesupport (>= 6.1.5)
|
||||||
|
i18n
|
||||||
|
rdoc (6.14.2)
|
||||||
|
erb
|
||||||
psych (>= 4.0.0)
|
psych (>= 4.0.0)
|
||||||
redis (5.2.0)
|
redis (5.4.1)
|
||||||
redis-client (>= 0.22.0)
|
redis-client (>= 0.22.0)
|
||||||
redis-client (0.22.2)
|
redis-client (0.25.2)
|
||||||
connection_pool
|
connection_pool
|
||||||
regexp_parser (2.9.2)
|
regexp_parser (2.11.2)
|
||||||
reline (0.5.9)
|
reline (0.6.2)
|
||||||
io-console (~> 0.5)
|
io-console (~> 0.5)
|
||||||
rexml (3.3.4)
|
rexml (3.4.1)
|
||||||
strscan
|
rubocop (1.79.2)
|
||||||
rubocop (1.65.1)
|
|
||||||
json (~> 2.3)
|
json (~> 2.3)
|
||||||
language_server-protocol (>= 3.17.0)
|
language_server-protocol (~> 3.17.0.2)
|
||||||
|
lint_roller (~> 1.1.0)
|
||||||
parallel (~> 1.10)
|
parallel (~> 1.10)
|
||||||
parser (>= 3.3.0.2)
|
parser (>= 3.3.0.2)
|
||||||
rainbow (>= 2.2.2, < 4.0)
|
rainbow (>= 2.2.2, < 4.0)
|
||||||
regexp_parser (>= 2.4, < 3.0)
|
regexp_parser (>= 2.9.3, < 3.0)
|
||||||
rexml (>= 3.2.5, < 4.0)
|
rubocop-ast (>= 1.46.0, < 2.0)
|
||||||
rubocop-ast (>= 1.31.1, < 2.0)
|
|
||||||
ruby-progressbar (~> 1.7)
|
ruby-progressbar (~> 1.7)
|
||||||
unicode-display_width (>= 2.4.0, < 3.0)
|
unicode-display_width (>= 2.4.0, < 4.0)
|
||||||
rubocop-ast (1.32.0)
|
rubocop-ast (1.46.0)
|
||||||
parser (>= 3.3.1.0)
|
parser (>= 3.3.7.2)
|
||||||
rubocop-minitest (0.35.1)
|
prism (~> 1.4)
|
||||||
rubocop (>= 1.61, < 2.0)
|
rubocop-performance (1.25.0)
|
||||||
rubocop-ast (>= 1.31.1, < 2.0)
|
lint_roller (~> 1.1)
|
||||||
rubocop-performance (1.21.1)
|
rubocop (>= 1.75.0, < 2.0)
|
||||||
rubocop (>= 1.48.1, < 2.0)
|
rubocop-ast (>= 1.38.0, < 2.0)
|
||||||
rubocop-ast (>= 1.31.1, < 2.0)
|
rubocop-rails (2.33.3)
|
||||||
rubocop-rails (2.25.1)
|
|
||||||
activesupport (>= 4.2.0)
|
activesupport (>= 4.2.0)
|
||||||
|
lint_roller (~> 1.1)
|
||||||
rack (>= 1.1)
|
rack (>= 1.1)
|
||||||
rubocop (>= 1.33.0, < 2.0)
|
rubocop (>= 1.75.0, < 2.0)
|
||||||
rubocop-ast (>= 1.31.1, < 2.0)
|
rubocop-ast (>= 1.44.0, < 2.0)
|
||||||
rubocop-rails-omakase (1.0.0)
|
rubocop-rails-omakase (1.1.0)
|
||||||
rubocop
|
rubocop (>= 1.72)
|
||||||
rubocop-minitest
|
rubocop-performance (>= 1.24)
|
||||||
rubocop-performance
|
rubocop-rails (>= 2.30)
|
||||||
rubocop-rails
|
ruby-next-core (1.1.2)
|
||||||
ruby-progressbar (1.13.0)
|
ruby-progressbar (1.13.0)
|
||||||
ruby-rc4 (0.1.5)
|
ruby-rc4 (0.1.5)
|
||||||
ruby-vips (2.2.2)
|
ruby-vips (2.2.4)
|
||||||
ffi (~> 1.12)
|
ffi (~> 1.12)
|
||||||
logger
|
logger
|
||||||
rubyzip (2.3.2)
|
rubyzip (3.0.1)
|
||||||
securerandom (0.3.1)
|
securerandom (0.4.1)
|
||||||
selenium-webdriver (4.23.0)
|
selenium-webdriver (4.35.0)
|
||||||
base64 (~> 0.2)
|
base64 (~> 0.2)
|
||||||
logger (~> 1.4)
|
logger (~> 1.4)
|
||||||
rexml (~> 3.2, >= 3.2.5)
|
rexml (~> 3.2, >= 3.2.5)
|
||||||
rubyzip (>= 1.2.2, < 3.0)
|
rubyzip (>= 1.2.2, < 4.0)
|
||||||
websocket (~> 1.0)
|
websocket (~> 1.0)
|
||||||
sprockets (4.2.1)
|
solid_cable (3.0.12)
|
||||||
|
actioncable (>= 7.2)
|
||||||
|
activejob (>= 7.2)
|
||||||
|
activerecord (>= 7.2)
|
||||||
|
railties (>= 7.2)
|
||||||
|
solid_cache (1.0.7)
|
||||||
|
activejob (>= 7.2)
|
||||||
|
activerecord (>= 7.2)
|
||||||
|
railties (>= 7.2)
|
||||||
|
solid_queue (1.2.1)
|
||||||
|
activejob (>= 7.1)
|
||||||
|
activerecord (>= 7.1)
|
||||||
|
concurrent-ruby (>= 1.3.1)
|
||||||
|
fugit (~> 1.11.0)
|
||||||
|
railties (>= 7.1)
|
||||||
|
thor (>= 1.3.1)
|
||||||
|
sprockets (4.2.2)
|
||||||
concurrent-ruby (~> 1.0)
|
concurrent-ruby (~> 1.0)
|
||||||
|
logger
|
||||||
rack (>= 2.2.4, < 4)
|
rack (>= 2.2.4, < 4)
|
||||||
sprockets-rails (3.5.2)
|
sprockets-rails (3.5.2)
|
||||||
actionpack (>= 6.1)
|
actionpack (>= 6.1)
|
||||||
activesupport (>= 6.1)
|
activesupport (>= 6.1)
|
||||||
sprockets (>= 3.0.0)
|
sprockets (>= 3.0.0)
|
||||||
sqlite3 (1.7.3-aarch64-linux)
|
sqlite3 (2.7.3-aarch64-linux-gnu)
|
||||||
sqlite3 (1.7.3-arm-linux)
|
sqlite3 (2.7.3-arm-linux-gnu)
|
||||||
sqlite3 (1.7.3-arm64-darwin)
|
sqlite3 (2.7.3-arm64-darwin)
|
||||||
sqlite3 (1.7.3-x86-linux)
|
sqlite3 (2.7.3-x86-linux-gnu)
|
||||||
sqlite3 (1.7.3-x86_64-darwin)
|
sqlite3 (2.7.3-x86_64-darwin)
|
||||||
sqlite3 (1.7.3-x86_64-linux)
|
sqlite3 (2.7.3-x86_64-linux-gnu)
|
||||||
stimulus-rails (1.3.3)
|
sshkit (1.24.0)
|
||||||
|
base64
|
||||||
|
logger
|
||||||
|
net-scp (>= 1.1.2)
|
||||||
|
net-sftp (>= 2.1.2)
|
||||||
|
net-ssh (>= 2.8.0)
|
||||||
|
ostruct
|
||||||
|
stimulus-rails (1.3.4)
|
||||||
railties (>= 6.0.0)
|
railties (>= 6.0.0)
|
||||||
stringio (3.1.1)
|
stringio (3.1.7)
|
||||||
strscan (3.1.0)
|
tailwindcss-rails (3.3.2)
|
||||||
tailwindcss-rails (2.7.2)
|
|
||||||
railties (>= 7.0.0)
|
railties (>= 7.0.0)
|
||||||
tailwindcss-rails (2.7.2-aarch64-linux)
|
tailwindcss-ruby (~> 3.0)
|
||||||
railties (>= 7.0.0)
|
tailwindcss-ruby (3.4.17)
|
||||||
tailwindcss-rails (2.7.2-arm-linux)
|
tailwindcss-ruby (3.4.17-aarch64-linux)
|
||||||
railties (>= 7.0.0)
|
tailwindcss-ruby (3.4.17-arm-linux)
|
||||||
tailwindcss-rails (2.7.2-arm64-darwin)
|
tailwindcss-ruby (3.4.17-arm64-darwin)
|
||||||
railties (>= 7.0.0)
|
tailwindcss-ruby (3.4.17-x86_64-darwin)
|
||||||
tailwindcss-rails (2.7.2-x86_64-darwin)
|
tailwindcss-ruby (3.4.17-x86_64-linux)
|
||||||
railties (>= 7.0.0)
|
thor (1.4.0)
|
||||||
tailwindcss-rails (2.7.2-x86_64-linux)
|
thruster (0.1.15)
|
||||||
railties (>= 7.0.0)
|
thruster (0.1.15-aarch64-linux)
|
||||||
thor (1.3.1)
|
thruster (0.1.15-arm64-darwin)
|
||||||
timeout (0.4.1)
|
thruster (0.1.15-x86_64-darwin)
|
||||||
|
thruster (0.1.15-x86_64-linux)
|
||||||
|
timeout (0.4.3)
|
||||||
ttfunk (1.8.0)
|
ttfunk (1.8.0)
|
||||||
bigdecimal (~> 3.1)
|
bigdecimal (~> 3.1)
|
||||||
turbo-rails (2.0.6)
|
turbo-rails (2.0.16)
|
||||||
actionpack (>= 6.0.0)
|
actionpack (>= 7.1.0)
|
||||||
activejob (>= 6.0.0)
|
railties (>= 7.1.0)
|
||||||
railties (>= 6.0.0)
|
|
||||||
tzinfo (2.0.6)
|
tzinfo (2.0.6)
|
||||||
concurrent-ruby (~> 1.0)
|
concurrent-ruby (~> 1.0)
|
||||||
unicode-display_width (2.5.0)
|
unicode-display_width (3.1.5)
|
||||||
useragent (0.16.10)
|
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)
|
web-console (4.2.1)
|
||||||
actionview (>= 6.0.0)
|
actionview (>= 6.0.0)
|
||||||
activemodel (>= 6.0.0)
|
activemodel (>= 6.0.0)
|
||||||
bindex (>= 0.4.0)
|
bindex (>= 0.4.0)
|
||||||
railties (>= 6.0.0)
|
railties (>= 6.0.0)
|
||||||
webrick (1.8.1)
|
|
||||||
websocket (1.2.11)
|
websocket (1.2.11)
|
||||||
websocket-driver (0.7.6)
|
websocket-driver (0.8.0)
|
||||||
|
base64
|
||||||
websocket-extensions (>= 0.1.0)
|
websocket-extensions (>= 0.1.0)
|
||||||
websocket-extensions (0.1.5)
|
websocket-extensions (0.1.5)
|
||||||
xpath (3.2.0)
|
xpath (3.2.0)
|
||||||
nokogiri (~> 1.8)
|
nokogiri (~> 1.8)
|
||||||
zeitwerk (2.6.17)
|
zeitwerk (2.7.3)
|
||||||
|
|
||||||
PLATFORMS
|
PLATFORMS
|
||||||
aarch64-linux
|
aarch64-linux
|
||||||
@@ -357,33 +437,43 @@ PLATFORMS
|
|||||||
x86_64-linux
|
x86_64-linux
|
||||||
|
|
||||||
DEPENDENCIES
|
DEPENDENCIES
|
||||||
|
action_policy (~> 0.7.1)
|
||||||
authentication-zero (~> 3.0)
|
authentication-zero (~> 3.0)
|
||||||
bcrypt (~> 3.1.7)
|
bcrypt (~> 3.1.7)
|
||||||
bootsnap
|
bootsnap
|
||||||
brakeman
|
brakeman
|
||||||
capybara
|
capybara
|
||||||
|
csv (~> 3.3)
|
||||||
debug
|
debug
|
||||||
faker (~> 3.4)
|
faker (~> 3.4)
|
||||||
image_processing (~> 1.2)
|
image_processing (~> 1.2)
|
||||||
importmap-rails
|
importmap-rails
|
||||||
inline_svg (~> 1.9)
|
inline_svg (~> 1.9)
|
||||||
jbuilder
|
jbuilder
|
||||||
|
kamal
|
||||||
kredis
|
kredis
|
||||||
letter_opener
|
letter_opener
|
||||||
|
pagy (~> 9.0)
|
||||||
pdf-reader (~> 2.12)
|
pdf-reader (~> 2.12)
|
||||||
puma (>= 5.0)
|
puma (>= 5.0)
|
||||||
pwned
|
pwned
|
||||||
rails (~> 7.2.0, >= 7.2.0)
|
rails (~> 8.0.0)
|
||||||
|
rails-i18n (~> 8.0)
|
||||||
|
ransack (~> 4.2)
|
||||||
redis (>= 4.0.1)
|
redis (>= 4.0.1)
|
||||||
rubocop-rails-omakase
|
rubocop-rails-omakase
|
||||||
selenium-webdriver
|
selenium-webdriver
|
||||||
|
solid_cable
|
||||||
|
solid_cache
|
||||||
|
solid_queue
|
||||||
sprockets-rails
|
sprockets-rails
|
||||||
sqlite3 (~> 1.4)
|
sqlite3 (>= 2.1)
|
||||||
stimulus-rails
|
stimulus-rails
|
||||||
tailwindcss-rails
|
tailwindcss-rails (~> 3.3.1)
|
||||||
|
thruster
|
||||||
turbo-rails
|
turbo-rails
|
||||||
tzinfo-data
|
tzinfo-data
|
||||||
web-console
|
web-console
|
||||||
|
|
||||||
BUNDLED WITH
|
BUNDLED WITH
|
||||||
2.5.17
|
2.7.1
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ Things you may want to cover:
|
|||||||
|
|
||||||
## System dependencies
|
## System dependencies
|
||||||
|
|
||||||
- poppler (PDF rendering libary)
|
- muPDF or poppler (PDF rendering libary)
|
||||||
- vips (Image processing libary)
|
- vips (Image processing libary)
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|||||||
@@ -13,3 +13,164 @@
|
|||||||
*= require_tree .
|
*= require_tree .
|
||||||
*= require_self
|
*= require_self
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
.turbo-progress-bar {
|
||||||
|
height: 5px;
|
||||||
|
background-color: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
.animate-job-in {
|
||||||
|
animation: fade-in 0.25s ease-out, slide-in 0.25s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.animate-job-out {
|
||||||
|
animation: fade-out 0.25s ease-out, slide-out 0.25s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.animate-fade-in {
|
||||||
|
animation: fade-in 0.25s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.animate-fade-out {
|
||||||
|
animation: fade-out 0.25s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fade-in {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fade-out {
|
||||||
|
from {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes slide-in {
|
||||||
|
from {
|
||||||
|
transform: translateX(4rem);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
transform: translateX(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes slide-out {
|
||||||
|
from {
|
||||||
|
transform: translateX(0);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
transform: translateX(4rem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.animate-job-item-in {
|
||||||
|
overflow: hidden;
|
||||||
|
animation: slide-down 0.5s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.animate-job-item-out {
|
||||||
|
overflow: hidden;
|
||||||
|
animation: slide-up 0.5s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* "max-height: auto" unfortunately does not work here, so we set
|
||||||
|
to a fixed height that is greater than the expected height. */
|
||||||
|
@keyframes slide-down {
|
||||||
|
from {
|
||||||
|
max-height: 0;
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
max-height: 3rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes slide-up {
|
||||||
|
from {
|
||||||
|
max-height: 3rem;
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
max-height: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.animate-flash-increase {
|
||||||
|
animation: flash-green 0.5s ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.animate-flash-decrease {
|
||||||
|
animation: flash-red 0.5s ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes flash-green {
|
||||||
|
from {
|
||||||
|
background-color: #a7f3d0;
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes flash-red {
|
||||||
|
from {
|
||||||
|
background-color: #fecaca;
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.animate-add-row {
|
||||||
|
transition-duration: 0.25s;
|
||||||
|
animation: addRow 0.25s 1 ease-out;
|
||||||
|
transform-origin: top;
|
||||||
|
}
|
||||||
|
|
||||||
|
.animate-rem-row {
|
||||||
|
transition-duration: 0.25s;
|
||||||
|
animation: remRow 0.25s 1 ease-out;
|
||||||
|
transform-origin: top;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes addRow {
|
||||||
|
0% {
|
||||||
|
transform: scale(1, 0);
|
||||||
|
line-height: 0px;
|
||||||
|
background-color: #fff;
|
||||||
|
visibility: collapse;
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
background-color: orange;
|
||||||
|
transform: scale(1, 1);
|
||||||
|
line-height: 18px; /* font-size(16px) + border-top(1px) + border-bottom(1px) */
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes remRow {
|
||||||
|
0% {
|
||||||
|
transform: scale(1, 0);
|
||||||
|
line-height: 18px; /* font-size(16px) + border-top(1px) + border-bottom(1px) */
|
||||||
|
background-color: #fff;
|
||||||
|
visibility: collapse;
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
background-color: orange;
|
||||||
|
transform: scale(1, 1);
|
||||||
|
line-height: 0px;
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
|
@import "pagy.tailwind.css";
|
||||||
|
|
||||||
@tailwind base;
|
@tailwind base;
|
||||||
@tailwind components;
|
@tailwind components;
|
||||||
@tailwind utilities;
|
@tailwind utilities;
|
||||||
|
|
||||||
|
|
||||||
@layer components {
|
@layer components {
|
||||||
.btn {
|
.btn {
|
||||||
@apply px-4 py-2 font-semibold text-white transition-colors duration-100 bg-opacity-100 shadow bg-hsrm-gray-light hover:bg-opacity-75 ;
|
@apply px-4 py-2 font-semibold text-white transition-colors duration-100 bg-opacity-100 shadow bg-hsrm-gray-light hover:bg-opacity-75 ;
|
||||||
@@ -9,11 +12,14 @@
|
|||||||
.btn-primary {
|
.btn-primary {
|
||||||
@apply bg-hsrm-red hover:bg-hsrm-red-light;
|
@apply bg-hsrm-red hover:bg-hsrm-red-light;
|
||||||
}
|
}
|
||||||
|
.btn-alert {
|
||||||
|
@apply bg-hsrm-red hover:bg-hsrm-red-light;
|
||||||
|
}
|
||||||
.badge {
|
.badge {
|
||||||
@apply text-sm font-medium text-center font-bold rounded-lg uppercase bg-gray-300 bg-opacity-50 px-2 py-1.5 shadow;
|
@apply text-sm font-medium text-center font-bold rounded-lg uppercase bg-gray-300 bg-opacity-50 px-2 py-1.5 shadow;
|
||||||
}
|
}
|
||||||
.badge-hover {
|
.badge-hover {
|
||||||
@apply p-1 hover:bg-opacity-75;
|
@apply hover:bg-opacity-75;
|
||||||
}
|
}
|
||||||
.badge-xl {
|
.badge-xl {
|
||||||
@apply text-2xl;
|
@apply text-2xl;
|
||||||
@@ -22,13 +28,13 @@
|
|||||||
@apply block w-24;
|
@apply block w-24;
|
||||||
}
|
}
|
||||||
.icon {
|
.icon {
|
||||||
@apply inline text-hsrm-gray size-7 drop-shadow hover:text-opacity-75;
|
@apply inline text-hsrm-gray size-7 drop-shadow;
|
||||||
}
|
}
|
||||||
.icon-disabled {
|
.icon-disabled {
|
||||||
@apply text-opacity-25 hover:text-opacity-25;
|
@apply text-opacity-25 hover:text-opacity-25;
|
||||||
}
|
}
|
||||||
.icon-nohover {
|
.icon-hover {
|
||||||
@apply hover:text-opacity-100;
|
@apply hover:text-opacity-75;
|
||||||
}
|
}
|
||||||
.card-status {
|
.card-status {
|
||||||
@apply uppercase shadow-lg bg-opacity-60 min-h-20 hover:bg-opacity-80;
|
@apply uppercase shadow-lg bg-opacity-60 min-h-20 hover:bg-opacity-80;
|
||||||
|
|||||||
21
app/assets/stylesheets/pagy.tailwind.css
Normal file
21
app/assets/stylesheets/pagy.tailwind.css
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
.pagy {
|
||||||
|
@apply flex pt-2 space-x-1 font-semibold text-gray-500;
|
||||||
|
a:not(.gap) {
|
||||||
|
@apply block px-3 py-1 bg-gray-200 shadow-lg;
|
||||||
|
&:hover {
|
||||||
|
@apply bg-gray-300;
|
||||||
|
}
|
||||||
|
&:not([href]) { /* disabled links */
|
||||||
|
@apply text-gray-300 bg-gray-100 cursor-default;
|
||||||
|
}
|
||||||
|
&.current {
|
||||||
|
@apply text-white bg-hsrm-red;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
label {
|
||||||
|
@apply inline-block whitespace-nowrap bg-gray-200 px-3 py-0.5;
|
||||||
|
input {
|
||||||
|
@apply bg-gray-100 border-none rounded-md;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
11
app/controllers/admin/dashboards_controller.rb
Normal file
11
app/controllers/admin/dashboards_controller.rb
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
class Admin::DashboardsController < ApplicationController
|
||||||
|
before_action :authorize!
|
||||||
|
def show
|
||||||
|
@user = User.all
|
||||||
|
@jobs = Job.all
|
||||||
|
end
|
||||||
|
|
||||||
|
def authorize!
|
||||||
|
super with: Admin::DashboardPolicy
|
||||||
|
end
|
||||||
|
end
|
||||||
19
app/controllers/admin/jobs_controller.rb
Normal file
19
app/controllers/admin/jobs_controller.rb
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
class Admin::JobsController < ApplicationController
|
||||||
|
include Pagy::Backend
|
||||||
|
|
||||||
|
before_action :authorize!
|
||||||
|
def index
|
||||||
|
@q = Job.ransack(params[:q])
|
||||||
|
@q.sorts = "id desc" if @q.sorts.empty?
|
||||||
|
# @pagy, @records = pagy(@q.result(distinct: true), limit: 20)
|
||||||
|
@calendar, @pagy, @records = pagy_calendar(@q.result, year: {}, month: {}, pagy: {}, active: params[:calendar])
|
||||||
|
end
|
||||||
|
|
||||||
|
def pagy_calendar_period(collection)
|
||||||
|
[ collection.minimum(:created_at).in_time_zone, collection.maximum(:created_at).in_time_zone ] if collection
|
||||||
|
end
|
||||||
|
|
||||||
|
def pagy_calendar_filter(collection, from, to)
|
||||||
|
collection.where(created_at: from...to)
|
||||||
|
end
|
||||||
|
end
|
||||||
46
app/controllers/admin/users_controller.rb
Normal file
46
app/controllers/admin/users_controller.rb
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
class Admin::UsersController < ApplicationController
|
||||||
|
include Pagy::Backend
|
||||||
|
|
||||||
|
before_action :set_user, only: [ :show, :update ]
|
||||||
|
before_action :authorize!
|
||||||
|
|
||||||
|
def index
|
||||||
|
# @users = User.all.order(:lastname, :firstname)
|
||||||
|
@q = User.ransack(params[:q])
|
||||||
|
@q.sorts = "id asc" if @q.sorts.empty?
|
||||||
|
@pagy, @records = pagy(@q.result(distinct: true), limit: 20)
|
||||||
|
end
|
||||||
|
|
||||||
|
def edit
|
||||||
|
end
|
||||||
|
|
||||||
|
def show
|
||||||
|
end
|
||||||
|
|
||||||
|
def new
|
||||||
|
end
|
||||||
|
|
||||||
|
def create
|
||||||
|
end
|
||||||
|
|
||||||
|
def update
|
||||||
|
authorize! @user, to: :change_role?
|
||||||
|
if @user.update(user_params)
|
||||||
|
respond_to do |format|
|
||||||
|
format.html { redirect_back(fallback_location: admin_users_path) }
|
||||||
|
end
|
||||||
|
else
|
||||||
|
render :index, status: :unprocessable_entity
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def set_user
|
||||||
|
@user = User.find(params[:id])
|
||||||
|
end
|
||||||
|
|
||||||
|
def user_params
|
||||||
|
params.require(:user).permit(:role)
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -1,6 +1,9 @@
|
|||||||
class ApplicationController < ActionController::Base
|
class ApplicationController < ActionController::Base
|
||||||
before_action :set_current_request_details
|
before_action :set_current_request_details
|
||||||
before_action :authenticate_user!
|
before_action :authenticate_user!
|
||||||
|
before_action :verified_user!
|
||||||
|
|
||||||
|
verify_authorized
|
||||||
|
|
||||||
private
|
private
|
||||||
def current_user
|
def current_user
|
||||||
@@ -25,6 +28,15 @@ class ApplicationController < ActionController::Base
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def verified_user!
|
||||||
|
if user_signed_in?
|
||||||
|
unless current_user.verified?
|
||||||
|
flash[:alert] = "Verify your email!"
|
||||||
|
redirect_to profile_path
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def set_current_request_details
|
def set_current_request_details
|
||||||
Current.user_agent = request.user_agent
|
Current.user_agent = request.user_agent
|
||||||
Current.ip_address = request.ip
|
Current.ip_address = request.ip
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
class Identity::EmailVerificationsController < ApplicationController
|
class Identity::EmailVerificationsController < ApplicationController
|
||||||
skip_before_action :authenticate_user!, only: :show
|
skip_before_action :authenticate_user!, only: :show
|
||||||
|
skip_before_action :verified_user!
|
||||||
|
skip_verify_authorized
|
||||||
|
|
||||||
before_action :set_user, only: :show
|
before_action :set_user, only: :show
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
class Identity::EmailsController < ApplicationController
|
class Identity::EmailsController < ApplicationController
|
||||||
|
skip_before_action :verified_user!
|
||||||
|
skip_verify_authorized
|
||||||
|
|
||||||
before_action :set_user
|
before_action :set_user
|
||||||
|
|
||||||
def edit
|
def edit
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
class Identity::PasswordResetsController < ApplicationController
|
class Identity::PasswordResetsController < ApplicationController
|
||||||
skip_before_action :authenticate_user!
|
skip_before_action :authenticate_user!
|
||||||
|
skip_verify_authorized
|
||||||
|
|
||||||
before_action :set_user, only: %i[ edit update ]
|
before_action :set_user, only: %i[ edit update ]
|
||||||
|
|
||||||
|
|||||||
@@ -1,18 +1,23 @@
|
|||||||
class JobsController < ApplicationController
|
class JobsController < ApplicationController
|
||||||
skip_before_action :authenticate_user!, only: :index
|
skip_before_action :authenticate_user!, only: [ :index, :cancel_button, :badge ]
|
||||||
|
skip_before_action :verified_user!, only: [ :index ]
|
||||||
|
skip_verify_authorized only: [ :index, :new, :create, :cancel_button, :badge]
|
||||||
|
|
||||||
# GET /jobs or /jobs.json
|
# GET /jobs or /jobs.json
|
||||||
def index
|
def index
|
||||||
@jobs = Job.currently_working_on
|
@jobs = Job.currently_working_on
|
||||||
|
@no_turbo_stream = true
|
||||||
end
|
end
|
||||||
|
|
||||||
# GET /jobs/new
|
# GET /jobs/new
|
||||||
def new
|
def new
|
||||||
@job = Job.new
|
@job = Job.new(customer_firstname: current_user.firstname, customer_lastname: current_user.lastname)
|
||||||
end
|
end
|
||||||
|
|
||||||
# POST /jobs or /jobs.json
|
# POST /jobs or /jobs.json
|
||||||
def create
|
def create
|
||||||
@job = Job.new(job_params)
|
@job = Job.new(job_params)
|
||||||
|
@job.customer = current_user
|
||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
if @job.save
|
if @job.save
|
||||||
@@ -27,6 +32,7 @@ class JobsController < ApplicationController
|
|||||||
|
|
||||||
def cancel
|
def cancel
|
||||||
@job = Job.find(params[:id])
|
@job = Job.find(params[:id])
|
||||||
|
authorize! @job
|
||||||
if @job.canceled!
|
if @job.canceled!
|
||||||
flash[:notice] = "Job successfully canceled"
|
flash[:notice] = "Job successfully canceled"
|
||||||
@status_changed = true
|
@status_changed = true
|
||||||
@@ -41,6 +47,18 @@ class JobsController < ApplicationController
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def cancel_button
|
||||||
|
@job = Job.find(params[:id])
|
||||||
|
|
||||||
|
render partial: "jobs/cancel_button", locals: { job: @job }
|
||||||
|
end
|
||||||
|
|
||||||
|
def badge
|
||||||
|
@job = Job.find(params[:id])
|
||||||
|
|
||||||
|
render partial: "jobs/badge", locals: { job: @job }
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def broadcast_update_status_cards_and_start_next_job_button
|
def broadcast_update_status_cards_and_start_next_job_button
|
||||||
@@ -60,7 +78,7 @@ class JobsController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def broadcast_create_job
|
def broadcast_create_job
|
||||||
Turbo::StreamsChannel.broadcast_prepend_later_to "jobs", target: :jobs, partial: "jobs/job_tr", locals: { job: @job }
|
Turbo::StreamsChannel.broadcast_append_later_to "jobs", target: :jobs, partial: "jobs/job_tr", locals: { job: @job }
|
||||||
Turbo::StreamsChannel.broadcast_append_later_to "operator_jobs", target: :openjobs, partial: "operator/jobs/job_tr", locals: { job: @job }
|
Turbo::StreamsChannel.broadcast_append_later_to "operator_jobs", target: :openjobs, partial: "operator/jobs/job_tr", locals: { job: @job }
|
||||||
broadcast_update_status_cards_and_start_next_job_button
|
broadcast_update_status_cards_and_start_next_job_button
|
||||||
end
|
end
|
||||||
@@ -83,6 +101,6 @@ class JobsController < ApplicationController
|
|||||||
|
|
||||||
# Only allow a list of trusted parameters through.
|
# Only allow a list of trusted parameters through.
|
||||||
def job_params
|
def job_params
|
||||||
params.require(:job).permit(:costumer_id, :costumer_firstname, :costumer_lastname, :privacy_policy_accepted, :pdf)
|
params.require(:job).permit(:customer_id, :customer_firstname, :customer_lastname, :privacy_policy, :pdf)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
class Operator::JobsController < ApplicationController
|
class Operator::JobsController < ApplicationController
|
||||||
before_action :set_job, only: %i[show edit update destroy increment_page decrement_page]
|
before_action :set_job, only: %i[show edit update destroy increment_page decrement_page]
|
||||||
before_action :set_job_lists, only: %i[index]
|
before_action :set_job_lists, only: %i[index]
|
||||||
|
before_action :authorize!
|
||||||
|
|
||||||
# GET /jobs or /jobs.json
|
# GET /jobs or /jobs.json
|
||||||
def index
|
def index
|
||||||
@@ -14,17 +15,14 @@ class Operator::JobsController < ApplicationController
|
|||||||
@job = Job.new
|
@job = Job.new
|
||||||
end
|
end
|
||||||
|
|
||||||
def egal
|
|
||||||
asdf
|
|
||||||
ddfd
|
|
||||||
end
|
|
||||||
|
|
||||||
# GET /jobs/1/edit
|
# GET /jobs/1/edit
|
||||||
def edit; end
|
def edit; end
|
||||||
|
|
||||||
# POST /jobs or /jobs.json
|
# POST /jobs or /jobs.json
|
||||||
def create
|
def create
|
||||||
@job = Job.new(job_params)
|
@job = Job.new(job_params)
|
||||||
|
@job.created_by_operator = true
|
||||||
|
@job.creator = current_user
|
||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
if @job.save
|
if @job.save
|
||||||
@@ -41,14 +39,15 @@ class Operator::JobsController < ApplicationController
|
|||||||
def update
|
def update
|
||||||
@job.assign_attributes(job_params)
|
@job.assign_attributes(job_params)
|
||||||
@status_changed = @job.status_changed?
|
@status_changed = @job.status_changed?
|
||||||
|
@job.current_user = current_user if @status_changed
|
||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
if @job.save
|
if @job.save
|
||||||
broadcast_update_job
|
broadcast_update_job
|
||||||
format.turbo_stream
|
format.turbo_stream unless request.referrer.include? "edit"
|
||||||
format.html { redirect_to operator_jobs_url, notice: "Job was successfully updated." }
|
format.html { redirect_to operator_jobs_url, notice: "Job was successfully updated." }
|
||||||
else
|
else
|
||||||
flash[:alert] = "Job was not updated."
|
flash[:alert] = "Job was not updated."
|
||||||
format.turbo_stream
|
|
||||||
format.html { render :edit, status: :unprocessable_entity }
|
format.html { render :edit, status: :unprocessable_entity }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -115,7 +114,7 @@ class Operator::JobsController < ApplicationController
|
|||||||
|
|
||||||
# Only allow a list of trusted parameters through.
|
# Only allow a list of trusted parameters through.
|
||||||
def job_params
|
def job_params
|
||||||
params.require(:job).permit(:operator_id, :costumer_id, :operator_firstname, :operator_lastname, :costumer_firstname, :costumer_lastname, :status)
|
params.require(:job).permit(:pdf, :operator_id, :customer_id, :operator_firstname, :operator_lastname, :customer_firstname, :customer_lastname, :status, :privacy_policy, :intern, :cost_center, :number_of_plans_a0, :number_of_plans_a1, :number_of_plans_a2, :number_of_plans_a3, :costum_qm_plan)
|
||||||
end
|
end
|
||||||
|
|
||||||
# FIXME: Move broadcast to model though i don't think view logic belongs in the model
|
# FIXME: Move broadcast to model though i don't think view logic belongs in the model
|
||||||
@@ -130,7 +129,7 @@ class Operator::JobsController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def broadcast_create_job
|
def broadcast_create_job
|
||||||
Turbo::StreamsChannel.broadcast_prepend_later_to "jobs", target: :jobs, partial: "jobs/job_tr", locals: { job: @job }
|
Turbo::StreamsChannel.broadcast_append_later_to "jobs", target: :jobs, partial: "jobs/job_tr", locals: { job: @job }
|
||||||
Turbo::StreamsChannel.broadcast_append_later_to "operator_jobs", target: :openjobs, partial: "operator/jobs/job_tr", locals: { job: @job }
|
Turbo::StreamsChannel.broadcast_append_later_to "operator_jobs", target: :openjobs, partial: "operator/jobs/job_tr", locals: { job: @job }
|
||||||
broadcast_update_status_cards_and_start_next_job_button
|
broadcast_update_status_cards_and_start_next_job_button
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
class PasswordsController < ApplicationController
|
class PasswordsController < ApplicationController
|
||||||
|
skip_verify_authorized only: [ :edit, :update ]
|
||||||
|
skip_before_action :verified_user!
|
||||||
before_action :set_user
|
before_action :set_user
|
||||||
|
|
||||||
def edit
|
def edit
|
||||||
|
|||||||
13
app/controllers/profiles_controller.rb
Normal file
13
app/controllers/profiles_controller.rb
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
class ProfilesController < ApplicationController
|
||||||
|
skip_verify_authorized only: [ :show, :edit, :destroy ]
|
||||||
|
skip_before_action :verified_user!
|
||||||
|
|
||||||
|
def show
|
||||||
|
end
|
||||||
|
|
||||||
|
def edit
|
||||||
|
end
|
||||||
|
|
||||||
|
def destroy
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
class RegistrationsController < ApplicationController
|
class RegistrationsController < ApplicationController
|
||||||
skip_before_action :authenticate_user!
|
skip_before_action :authenticate_user!
|
||||||
|
skip_verify_authorized
|
||||||
|
|
||||||
|
|
||||||
def new
|
def new
|
||||||
@user = User.new
|
@user = User.new
|
||||||
@@ -21,7 +23,7 @@ class RegistrationsController < ApplicationController
|
|||||||
|
|
||||||
private
|
private
|
||||||
def user_params
|
def user_params
|
||||||
params.permit(:email, :password, :password_confirmation)
|
params.permit(:email, :firstname, :lastname, :password, :password_confirmation)
|
||||||
end
|
end
|
||||||
|
|
||||||
def send_email_verification
|
def send_email_verification
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
class SessionsController < ApplicationController
|
class SessionsController < ApplicationController
|
||||||
skip_before_action :authenticate_user!, only: %i[ new create ]
|
skip_before_action :authenticate_user!, only: %i[ new create ]
|
||||||
|
skip_before_action :verified_user!
|
||||||
|
skip_verify_authorized only: [ :index, :new, :create, :destroy ]
|
||||||
|
|
||||||
before_action :set_session, only: :destroy
|
before_action :set_session, only: :destroy
|
||||||
|
|
||||||
@@ -22,7 +24,12 @@ class SessionsController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
@session.destroy; redirect_to(sessions_path, notice: "That session has been logged out")
|
@session.destroy
|
||||||
|
if Current.session == @session
|
||||||
|
redirect_to(root_path, notice: "You are logged out")
|
||||||
|
else
|
||||||
|
redirect_to(sessions_path, notice: "That session has been logged out")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|||||||
2
app/helpers/admin/dashboards_helper.rb
Normal file
2
app/helpers/admin/dashboards_helper.rb
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
module Admin::DashboardsHelper
|
||||||
|
end
|
||||||
3
app/helpers/admin/jobs_helper.rb
Normal file
3
app/helpers/admin/jobs_helper.rb
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
module Admin::JobsHelper
|
||||||
|
include Pagy::Frontend
|
||||||
|
end
|
||||||
3
app/helpers/admin/users_helper.rb
Normal file
3
app/helpers/admin/users_helper.rb
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
module Admin::UsersHelper
|
||||||
|
include Pagy::Frontend
|
||||||
|
end
|
||||||
@@ -3,11 +3,43 @@ module ApplicationHelper
|
|||||||
options[:title] ||= name.underscore.humanize
|
options[:title] ||= name.underscore.humanize
|
||||||
options[:aria] = true
|
options[:aria] = true
|
||||||
options[:nocomment] = true
|
options[:nocomment] = true
|
||||||
options[:variant] ||= :outline
|
options[:variant] ||= :outline # :outline, :solid
|
||||||
#options[:class] = options.fetch(:class, nil)
|
# options[:class] = options.fetch(:class, nil)
|
||||||
options[:class] = "size-5" unless options[:class]
|
options[:class] = "size-5" unless options[:class]
|
||||||
path = options.fetch(:path, "icons/#{options[:variant]}/#{name}.svg")
|
path = options.fetch(:path, "icons/#{options[:variant]}/#{name}.svg")
|
||||||
icon = path
|
icon = path
|
||||||
inline_svg_tag(icon, options)
|
inline_svg_tag(icon, options)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def bool_icon(bool)
|
||||||
|
case bool
|
||||||
|
when true then "check-circle"
|
||||||
|
else "x-circle"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def operator_tab?
|
||||||
|
controller.class.name.split("::").first=="Operator"
|
||||||
|
end
|
||||||
|
|
||||||
|
def admin_tab?
|
||||||
|
controller.class.name.split("::").first=="Admin"
|
||||||
|
end
|
||||||
|
|
||||||
|
def profile_tab?
|
||||||
|
controller.class.name=="ProfilesController"
|
||||||
|
end
|
||||||
|
|
||||||
|
def root_tab?
|
||||||
|
controller.class.name=="JobsController"
|
||||||
|
end
|
||||||
|
|
||||||
|
def is_admin_or_operator?
|
||||||
|
current_user.admin? || current_user.operator?
|
||||||
|
end
|
||||||
|
|
||||||
|
def edit_form?
|
||||||
|
action_name != "new" && action_name != "create"
|
||||||
|
# alternate: @model.persisted?
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
2
app/helpers/profiles_helper.rb
Normal file
2
app/helpers/profiles_helper.rb
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
module ProfilesHelper
|
||||||
|
end
|
||||||
@@ -7,3 +7,47 @@ application.debug = false
|
|||||||
window.Stimulus = application
|
window.Stimulus = application
|
||||||
|
|
||||||
export { application }
|
export { application }
|
||||||
|
|
||||||
|
// Transition for turbo_frames
|
||||||
|
// URL: https://dev.to/nejremeslnici/how-to-use-view-transitions-in-hotwire-turbo-1kdi
|
||||||
|
// Alternative turbo_stream URL: https://evilmartians.com/chronicles/the-future-of-full-stack-rails-turbo-view-transitions
|
||||||
|
addEventListener("turbo:before-frame-render", (event) => {
|
||||||
|
if (document.startViewTransition) {
|
||||||
|
const originalRender = event.detail.render
|
||||||
|
event.detail.render = (currentElement, newElement) => {
|
||||||
|
document.startViewTransition(()=> originalRender(currentElement, newElement))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// URL: https://edforshaw.co.uk/hotwire-turbo-stream-animations
|
||||||
|
// and: https://stackoverflow.com/questions/61306601/css-animation-on-table-row-how-to-affect-height
|
||||||
|
// Alternative Hotwire Animate (Wrapper for Animate.css)
|
||||||
|
// URL: https://railshackathon.com/entries/12 https://yozu.co.uk/tech-blog-turbocharged-animations-introducing-hotwire-animate/
|
||||||
|
// Discussion about hotwire animation: https://discuss.hotwired.dev/t/are-transitions-and-animations-on-hotwire-roadmap/1547/10
|
||||||
|
document.addEventListener("turbo:before-stream-render", (event) => {
|
||||||
|
// Add a class to an element we are about to add to the page
|
||||||
|
// as defined by its "data-stream-enter-class"
|
||||||
|
if (event.target.firstElementChild instanceof HTMLTemplateElement) {
|
||||||
|
var enterAnimationClass = event.target.templateContent.firstElementChild.dataset.streamEnterClass
|
||||||
|
if (enterAnimationClass) {
|
||||||
|
event.target.templateElement.content.firstElementChild.classList.add(enterAnimationClass)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Add a class to an element we are about to remove from the page
|
||||||
|
// as defined by its "data-stream-exit-class"
|
||||||
|
var elementToRemove = document.getElementById(event.target.target)
|
||||||
|
if (elementToRemove) {
|
||||||
|
var streamExitClass = elementToRemove.dataset.streamExitClass
|
||||||
|
if (streamExitClass) {
|
||||||
|
// Intercept the removal of the element
|
||||||
|
event.preventDefault()
|
||||||
|
// elementToRemove.classList.remove(elementToRemove.dataset.streamEnterClass)
|
||||||
|
elementToRemove.classList.add(streamExitClass)
|
||||||
|
// Wait for its animation to end before removing the element
|
||||||
|
elementToRemove.addEventListener("animationend", function() {
|
||||||
|
event.target.performAction()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|||||||
@@ -1,38 +1,51 @@
|
|||||||
class Job < ApplicationRecord
|
class Job < ApplicationRecord
|
||||||
belongs_to :operator, class_name: "User", optional: true
|
attr_accessor :current_user
|
||||||
belongs_to :costumer, class_name: "User", optional: true
|
|
||||||
|
belongs_to :customer, class_name: "User", optional: true, counter_cache: :customer_jobs_count, inverse_of: :customer_jobs
|
||||||
|
belongs_to :operator, class_name: "User", optional: true, counter_cache: :operator_jobs_count, inverse_of: :operator_jobs
|
||||||
|
belongs_to :creator, class_name: "User", optional: true, counter_cache: :created_jobs_count, inverse_of: :created_jobs
|
||||||
|
belongs_to :cashier, class_name: "User", optional: true, counter_cache: :cashed_jobs_count, inverse_of: :cashed_jobs
|
||||||
|
|
||||||
has_one_attached :pdf, dependent: :purge
|
has_one_attached :pdf, dependent: :purge
|
||||||
|
|
||||||
validates_presence_of :costumer_firstname, :costumer_lastname, :privacy_policy_accepted, :pdf
|
validates_presence_of :customer_firstname, :customer_lastname
|
||||||
# validates_numericality_of {:number_of_plans_a0,:number_of_plans_a1, :number_of_plans_a2, :number_of_plans_a3}, greater_than_or_equal_to: 0
|
validates_presence_of :cost_center, if: :intern
|
||||||
validates :number_of_plans_a0, :number_of_plans_a1, :number_of_plans_a2, :number_of_plans_a3, numericality: { greater_than_or_equal_to: 0 }
|
validates_presence_of :pdf, unless: :created_by_operator?
|
||||||
|
validates :privacy_policy, acceptance: true, unless: :created_by_operator?
|
||||||
|
validates :number_of_plans_a0, :number_of_plans_a1, :number_of_plans_a2, :number_of_plans_a3, :costum_qm_plan, numericality: { greater_than_or_equal_to: 0 }
|
||||||
|
validate :acceptable_pdf, unless: :created_by_operator?
|
||||||
|
|
||||||
|
|
||||||
validate :acceptable_pdf
|
|
||||||
|
|
||||||
before_save :update_printed_at, if: :will_save_change_to_status?
|
|
||||||
before_save :update_paid_at, if: :will_save_change_to_status?
|
|
||||||
before_save :update_status_changed_at, if: :will_save_change_to_status?
|
before_save :update_status_changed_at, if: :will_save_change_to_status?
|
||||||
|
before_save :update_user_status_infos, if: -> { will_save_change_to_status? || new_record? }
|
||||||
|
|
||||||
before_save :set_cost_qm
|
before_save :set_cost_qm
|
||||||
before_save :calc_cost, if: :printed_pages_changes?
|
before_save :calc_cost, if: :printed_pages_changes?
|
||||||
|
|
||||||
|
before_validation :set_customer_infos, unless: :created_by_operator?, on: :create
|
||||||
|
|
||||||
# TODO: works only when job is created. Should move analyzer to activestorage :
|
# TODO: works only when job is created. Should move analyzer to activestorage :
|
||||||
# https://discuss.rubyonrails.org/t/active-storage-in-production-lessons-learned-and-in-depth-look-at-how-it-works/83289
|
# https://discuss.rubyonrails.org/t/active-storage-in-production-lessons-learned-and-in-depth-look-at-how-it-works/83289
|
||||||
# https://redgreen.no/2021/01/24/custom-analyzer-for-activestorage.html
|
# https://redgreen.no/2021/01/24/custom-analyzer-for-activestorage.html
|
||||||
|
# Possible alternative
|
||||||
|
# https://github.com/shrinerb/shrine
|
||||||
after_create_commit :analyze_pdf
|
after_create_commit :analyze_pdf
|
||||||
|
|
||||||
# NOTE: Multiple status if paing before brinting?
|
# NOTE: Multiple status if paing before brinting?
|
||||||
enum :status, {
|
enum :status, {
|
||||||
open: 0,
|
open: "open",
|
||||||
printing: 1,
|
printing: "printing",
|
||||||
pickup: 2,
|
pickup: "pickup",
|
||||||
paid: 3,
|
paid: "paid",
|
||||||
canceled: 4
|
canceled: "canceled"
|
||||||
}
|
}
|
||||||
|
|
||||||
AVAILABLE_PAGE_FORMATS = [ :a0, :a1, :a2, :a3 ]
|
AVAILABLE_PAGE_FORMATS = [ :a0, :a1, :a2, :a3 ]
|
||||||
|
|
||||||
|
# scope :created_as_operator, -> { where created_as_operator: true }
|
||||||
|
# scope :created_as_customer, -> { where created_as_operator: false }
|
||||||
|
scope :not_canceled, -> { !canceled }
|
||||||
|
|
||||||
# NOTE: only named status are returned because of WHERE/IN clause for the enum values
|
# NOTE: only named status are returned because of WHERE/IN clause for the enum values
|
||||||
scope :in_status_order, -> { in_order_of(:status, %w[open printing pickup paid canceled]) }
|
scope :in_status_order, -> { in_order_of(:status, %w[open printing pickup paid canceled]) }
|
||||||
|
|
||||||
@@ -48,6 +61,8 @@ class Job < ApplicationRecord
|
|||||||
scope :status_changed_on_day, lambda { |date|
|
scope :status_changed_on_day, lambda { |date|
|
||||||
where("status_changed_at >= ? AND status_changed_at <= ?", date.beginning_of_day, date.end_of_day)
|
where("status_changed_at >= ? AND status_changed_at <= ?", date.beginning_of_day, date.end_of_day)
|
||||||
}
|
}
|
||||||
|
scope :created_by_customer, -> { not(:created_by_operator) }
|
||||||
|
|
||||||
# Returns all jobs with status: open print pickup and jobs from today with status: paid canceled
|
# Returns all jobs with status: open print pickup and jobs from today with status: paid canceled
|
||||||
# paid: only updated_at today
|
# paid: only updated_at today
|
||||||
# canceled: only updated_at today
|
# canceled: only updated_at today
|
||||||
@@ -58,7 +73,7 @@ class Job < ApplicationRecord
|
|||||||
.where("status_changed_at >= ?", Time.now.beginning_of_day))
|
.where("status_changed_at >= ?", Time.now.beginning_of_day))
|
||||||
# .in_status_order
|
# .in_status_order
|
||||||
.order(created_at: :asc)
|
.order(created_at: :asc)
|
||||||
# .order(:costumer_firstname, :costumer_lastname)
|
# .order(:customer_firstname, :customer_lastname)
|
||||||
.with_attached_pdf # scope from activestorage for .includes(pdf_attachment: :blob)
|
.with_attached_pdf # scope from activestorage for .includes(pdf_attachment: :blob)
|
||||||
# .references(:pdf_attachment, :blob) # creates big join table
|
# .references(:pdf_attachment, :blob) # creates big join table
|
||||||
end
|
end
|
||||||
@@ -67,8 +82,8 @@ class Job < ApplicationRecord
|
|||||||
Job.where(status: %i[paid canceled])
|
Job.where(status: %i[paid canceled])
|
||||||
end
|
end
|
||||||
|
|
||||||
def costumer_fullname
|
def customer_fullname
|
||||||
[ costumer_firstname, " ", costumer_lastname ].join
|
[ customer_firstname, " ", customer_lastname ].join
|
||||||
end
|
end
|
||||||
|
|
||||||
def acceptable_pdf
|
def acceptable_pdf
|
||||||
@@ -107,18 +122,29 @@ class Job < ApplicationRecord
|
|||||||
save
|
save
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def self.report_to_csv(jobs)
|
||||||
|
columns_readable = [ "ID", "Kunde Vorname", "Kunde Nachname", "Kassierer Vorname", "Kassierer Nachname", "bezahlt am", "Betrag" ]
|
||||||
|
CSV.generate(col_sep: ";") do |csv|
|
||||||
|
csv << columns_readable
|
||||||
|
jobs.each do |job|
|
||||||
|
# csv << job.attributes.values_at(*columns)
|
||||||
|
csv << [ job.id, job.customer_firstname, job.customer_lastname, job.cashier_firstname, job.cashier_lastname, job.paid_at.localtime.strftime("%Y-%m-%d"), job.cost.to_s + " €" ]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.ransackable_attributes(auth_object = nil)
|
||||||
|
[ "created_at", "id", "customer_firstname", "customer_lastname", "pdf.", "created_by_operator", "number_of_plans_a0", "number_of_plans_a1", "number_of_plans_a2", "number_of_plans_a3", "costum_qm_plan", "cost", "status" ]
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.ransackable_associations(auth_object = nil)
|
||||||
|
[ "pdf_blob" ]
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def printed_pages_changes?
|
def printed_pages_changes?
|
||||||
costum_qm_plan_previously_changed? || number_of_plans_a0_changed? || number_of_plans_a1_changed? || number_of_plans_a2_changed? || number_of_plans_a3_changed?
|
costum_qm_plan_changed? || number_of_plans_a0_changed? || number_of_plans_a1_changed? || number_of_plans_a2_changed? || number_of_plans_a3_changed?
|
||||||
end
|
|
||||||
|
|
||||||
def update_printed_at
|
|
||||||
self.printed_at = Time.now if pickup? || (paid? && printed_at.nil?)
|
|
||||||
end
|
|
||||||
|
|
||||||
def update_paid_at
|
|
||||||
self.paid_at = Time.now if paid?
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def update_status_changed_at
|
def update_status_changed_at
|
||||||
@@ -128,7 +154,7 @@ class Job < ApplicationRecord
|
|||||||
def calc_cost
|
def calc_cost
|
||||||
self.cost = (number_of_plans_a0 * cost_qm) + (number_of_plans_a1 * cost_qm / 2) +
|
self.cost = (number_of_plans_a0 * cost_qm) + (number_of_plans_a1 * cost_qm / 2) +
|
||||||
(number_of_plans_a2 * cost_qm / 4) + (number_of_plans_a3 * cost_qm / 8) +
|
(number_of_plans_a2 * cost_qm / 4) + (number_of_plans_a3 * cost_qm / 8) +
|
||||||
(costum_qm_plan * cost_qm)
|
(costum_qm_plan * cost_qm).round(2)
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_cost_qm
|
def set_cost_qm
|
||||||
@@ -147,18 +173,92 @@ class Job < ApplicationRecord
|
|||||||
# TODO: add any check if attachment has changed
|
# TODO: add any check if attachment has changed
|
||||||
|
|
||||||
# pdfs.each do |pdf|
|
# pdfs.each do |pdf|
|
||||||
pdf.blob.open do |file|
|
if pdf.blob
|
||||||
# file = ActiveStorage::Blob.service.path_for(pdf.key).to_s
|
pdf.blob.open do |file|
|
||||||
pdf_analyzer = Services::PdfAnalyzer.new(file)
|
# file = ActiveStorage::Blob.service.path_for(pdf.key).to_s
|
||||||
pdf_analyzer.analyze
|
pdf_analyzer = Services::PdfAnalyzer.new(file)
|
||||||
self.number_of_plans_a0 += pdf_analyzer.pages_a0
|
pdf_analyzer.analyze
|
||||||
self.number_of_plans_a1 += pdf_analyzer.pages_a1
|
self.number_of_plans_a0 += pdf_analyzer.pages_a0
|
||||||
self.number_of_plans_a2 += pdf_analyzer.pages_a2
|
self.number_of_plans_a1 += pdf_analyzer.pages_a1
|
||||||
self.number_of_plans_a3 += pdf_analyzer.pages_a3
|
self.number_of_plans_a2 += pdf_analyzer.pages_a2
|
||||||
self.costum_qm_plan += pdf_analyzer.costum_qm
|
self.number_of_plans_a3 += pdf_analyzer.pages_a3
|
||||||
|
self.costum_qm_plan += pdf_analyzer.costum_qm
|
||||||
|
end
|
||||||
end
|
end
|
||||||
# end
|
# end
|
||||||
calc_cost
|
calc_cost
|
||||||
save
|
save
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def set_customer_infos
|
||||||
|
self.customer = current_user unless self.customer
|
||||||
|
self.customer_firstname = customer.firstname
|
||||||
|
self.customer_lastname = customer.lastname
|
||||||
|
end
|
||||||
|
|
||||||
|
def set_operator_infos
|
||||||
|
self.operator = current_user unless self.operator
|
||||||
|
self.operator_firstname = operator.firstname
|
||||||
|
self.operator_lastname = operator.lastname
|
||||||
|
end
|
||||||
|
|
||||||
|
def clear_operator_infos
|
||||||
|
self.operator = nil
|
||||||
|
self.operator_firstname = nil
|
||||||
|
self.operator_lastname = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def operator_infos_set?
|
||||||
|
self.operator && self.operator_firstname && self.operator_lastname
|
||||||
|
end
|
||||||
|
|
||||||
|
def set_cashier_infos
|
||||||
|
self.paid_at = Time.now
|
||||||
|
self.cashier = current_user unless self.cashier
|
||||||
|
self.cashier_firstname = cashier.firstname
|
||||||
|
self.cashier_lastname = cashier.lastname
|
||||||
|
end
|
||||||
|
|
||||||
|
def clear_cashier_infos
|
||||||
|
self.paid_at = nil
|
||||||
|
self.cashier = nil
|
||||||
|
self.cashier_firstname = nil
|
||||||
|
self.cashier_lastname = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
def reset_operator_and_cashier_infos
|
||||||
|
clear_operator_infos
|
||||||
|
clear_cashier_infos
|
||||||
|
end
|
||||||
|
|
||||||
|
def update_user_status_infos
|
||||||
|
case status.to_sym
|
||||||
|
when :open
|
||||||
|
reset_operator_and_cashier_infos
|
||||||
|
self.printed_at = nil
|
||||||
|
self.paid_at = nil
|
||||||
|
when :printing
|
||||||
|
set_operator_infos
|
||||||
|
clear_cashier_infos
|
||||||
|
self.printed_at = nil
|
||||||
|
when :pickup
|
||||||
|
set_operator_infos unless operator_infos_set?
|
||||||
|
clear_cashier_infos
|
||||||
|
self.printed_at = Time.now unless self.printed_at
|
||||||
|
when :canceled
|
||||||
|
clear_operator_infos
|
||||||
|
clear_cashier_infos
|
||||||
|
self.printed_at = nil
|
||||||
|
when :paid
|
||||||
|
set_operator_infos unless operator_infos_set?
|
||||||
|
self.printed_at = Time.now unless self.printed_at
|
||||||
|
set_cashier_infos
|
||||||
|
self.paid_at = Time.now
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def reset_to_status_open?
|
||||||
|
status_changed? && open?
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
class User < ApplicationRecord
|
class User < ApplicationRecord
|
||||||
has_secure_password
|
has_secure_password
|
||||||
has_many :jobs_as_costumer, foreign_key: :costumer_id, class_name: "Job"
|
# has_many :jobs
|
||||||
has_many :jobs_as_operator, foreign_key: :operator_id, class_name: "Job"
|
has_many :customer_jobs, foreign_key: :customer_id, class_name: "Job"
|
||||||
|
has_many :operator_jobs, foreign_key: :operator_id, class_name: "Job"
|
||||||
|
has_many :created_jobs, foreign_key: :creator_id, class_name: "Job"
|
||||||
|
has_many :cashed_jobs, foreign_key: :cashier_id, class_name: "Job"
|
||||||
|
|
||||||
generates_token_for :email_verification, expires_in: 2.days do
|
generates_token_for :email_verification, expires_in: 2.days do
|
||||||
email
|
email
|
||||||
@@ -17,14 +20,16 @@ class User < ApplicationRecord
|
|||||||
format: { with: /\b[A-Z0-9._%a-z\-]+@(student\.|)hs\-rm\.de\z/, message: "must be a student.hs-rm.de or hs-rm.de email" }
|
format: { with: /\b[A-Z0-9._%a-z\-]+@(student\.|)hs\-rm\.de\z/, message: "must be a student.hs-rm.de or hs-rm.de email" }
|
||||||
|
|
||||||
validates :password, allow_nil: true, length: { minimum: 12 }
|
validates :password, allow_nil: true, length: { minimum: 12 }
|
||||||
validates :password, not_pwned: { message: "might easily be guessed" }
|
# validates :password, not_pwned: { message: "might easily be guessed" }
|
||||||
|
|
||||||
|
validates_presence_of :firstname, :lastname
|
||||||
|
|
||||||
normalizes :email, with: -> { _1.strip.downcase }
|
normalizes :email, with: -> { _1.strip.downcase }
|
||||||
|
|
||||||
enum :role, {
|
enum :role, {
|
||||||
user: 0,
|
user: "user",
|
||||||
operator: 1,
|
operator: "operator",
|
||||||
admin: 2
|
admin: "admin"
|
||||||
}
|
}
|
||||||
|
|
||||||
before_validation if: :email_changed?, on: :update do
|
before_validation if: :email_changed?, on: :update do
|
||||||
@@ -34,4 +39,20 @@ class User < ApplicationRecord
|
|||||||
after_update if: :password_digest_previously_changed? do
|
after_update if: :password_digest_previously_changed? do
|
||||||
sessions.where.not(id: Current.session).delete_all
|
sessions.where.not(id: Current.session).delete_all
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def name
|
||||||
|
[ firstname, " ", lastname ].join
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.ransackable_attributes(auth_object = nil)
|
||||||
|
[ "created_at", "email", "firstname", "id", "customer_jobs_count", "operator_jobs_count", "lastname", "role", "verified", "name" ]
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.ransackable_associations(auth_object = nil)
|
||||||
|
[]
|
||||||
|
end
|
||||||
|
|
||||||
|
ransacker :name do
|
||||||
|
Arel.sql("CONCAT_WS(' ', users.firstname, users.lastname)")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
2
app/policies/admin/dashboard_policy.rb
Normal file
2
app/policies/admin/dashboard_policy.rb
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
class Admin::DashboardPolicy < ApplicationPolicy
|
||||||
|
end
|
||||||
2
app/policies/admin/job_policy.rb
Normal file
2
app/policies/admin/job_policy.rb
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
class Admin::JobPolicy < ApplicationPolicy
|
||||||
|
end
|
||||||
7
app/policies/admin/user_policy.rb
Normal file
7
app/policies/admin/user_policy.rb
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
class Admin::UserPolicy < ApplicationPolicy
|
||||||
|
skip_pre_check :allow_admins, only: :change_role?
|
||||||
|
|
||||||
|
def change_role?
|
||||||
|
user.admin? and user != record
|
||||||
|
end
|
||||||
|
end
|
||||||
39
app/policies/application_policy.rb
Normal file
39
app/policies/application_policy.rb
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
# Base class for application policies
|
||||||
|
class ApplicationPolicy < ActionPolicy::Base
|
||||||
|
pre_check :allow_admins, :deny_unverified_users
|
||||||
|
|
||||||
|
# admin is good! :)
|
||||||
|
def allow_admins
|
||||||
|
allow! if user.admin?
|
||||||
|
end
|
||||||
|
|
||||||
|
# no email verification no rights
|
||||||
|
def deny_unverified_users
|
||||||
|
deny! unless user.verified?
|
||||||
|
end
|
||||||
|
|
||||||
|
def operate?
|
||||||
|
allow! if user.operator? || user.admin?
|
||||||
|
end
|
||||||
|
|
||||||
|
def admin?
|
||||||
|
allow! if user.admin?
|
||||||
|
end
|
||||||
|
|
||||||
|
# Configure additional authorization contexts here
|
||||||
|
# (`user` is added by default).
|
||||||
|
#
|
||||||
|
# authorize :account, optional: true
|
||||||
|
#
|
||||||
|
# Read more about authorization context: https://actionpolicy.evilmartians.io/#/authorization_context
|
||||||
|
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
# Define shared methods useful for most policies.
|
||||||
|
# For example:
|
||||||
|
#
|
||||||
|
# def owner?
|
||||||
|
# record.user_id == user.id
|
||||||
|
# end
|
||||||
|
end
|
||||||
23
app/policies/job_policy.rb
Normal file
23
app/policies/job_policy.rb
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
class JobPolicy < ApplicationPolicy
|
||||||
|
skip_pre_check :allow_admins, only: :cancel?
|
||||||
|
|
||||||
|
def cancel?
|
||||||
|
record.open? && (user == record.customer || user.operator? || user.admin?)
|
||||||
|
end
|
||||||
|
|
||||||
|
# See https://actionpolicy.evilmartians.io/#/writing_policies
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# def update?
|
||||||
|
# # here we can access our context and record
|
||||||
|
# user.admin? || (user.id == record.user_id)
|
||||||
|
# end
|
||||||
|
|
||||||
|
# Scoping
|
||||||
|
# See https://actionpolicy.evilmartians.io/#/scoping
|
||||||
|
#
|
||||||
|
# relation_scope do |relation|
|
||||||
|
# next relation if user.admin?
|
||||||
|
# relation.where(user: user)
|
||||||
|
# end
|
||||||
|
end
|
||||||
9
app/policies/operator/job_policy.rb
Normal file
9
app/policies/operator/job_policy.rb
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
class Operator::JobPolicy < ApplicationPolicy
|
||||||
|
pre_check :allow_operators
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def allow_operators
|
||||||
|
allow! if user.operator?
|
||||||
|
end
|
||||||
|
end
|
||||||
5
app/policies/session_policy.rb
Normal file
5
app/policies/session_policy.rb
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
class SessionPolicy < ApplicationPolicy
|
||||||
|
def new?
|
||||||
|
true
|
||||||
|
end
|
||||||
|
end
|
||||||
44
app/views/admin/dashboards/show.html.erb
Normal file
44
app/views/admin/dashboards/show.html.erb
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
<div>
|
||||||
|
<h1 class="text-4xl font-bold">Admin::Dashboards#show</h1>
|
||||||
|
<p>Find me in app/views/admin/dashboards/show.html.erb</p>
|
||||||
|
<ul>
|
||||||
|
<li>Übersicht Druckaufträge (Abgerechnet/Kostenstelle/Pro Monat/CSV Export)</li>
|
||||||
|
<li>Übersicht Benutzer (Detailansicht/Statisiken/Jobs)</li>
|
||||||
|
<li>Übersicht Tutoren (Statistiken/Jobs)</li>
|
||||||
|
<li>Drucker?(Statistiken/Jobs/Verbrauchsmaterialien )</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="flex space-x-2">
|
||||||
|
<%= link_to admin_users_path() do %>
|
||||||
|
<div class="p-4 shadow bg-gray-50">
|
||||||
|
<h2 class="text-xl">Benutzer:</h2>
|
||||||
|
<p class="size-28"><%= @user.size %></p>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
<%= link_to admin_users_path(q: { role_eq: "operator"}) do %>
|
||||||
|
<div class="p-4 shadow bg-gray-50">
|
||||||
|
<h2 class="text-xl">Operatoren:</h2>
|
||||||
|
<p class="size-28"><%= @user.operator.size %></p>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
<%= link_to admin_users_path(q: { role_eq: "admin"}) do %>
|
||||||
|
<div class="p-4 shadow bg-gray-50">
|
||||||
|
<h2 class="text-xl">Admins:</h2>
|
||||||
|
<p class="size-28"><%= @user.admin.size %></p>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
|
<div class="flex space-x-2">
|
||||||
|
<%= link_to operator_jobs_path() do %>
|
||||||
|
<div class="p-4 shadow bg-gray-50">
|
||||||
|
<h2 class="text-xl">Heutige Druckaufträge:</h2>
|
||||||
|
<p class="size-28"><%= @jobs.currently_working_on.size %></p>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
<%= link_to admin_jobs_path() do %>
|
||||||
|
<div class="p-4 shadow bg-gray-50">
|
||||||
|
<h2 class="text-xl">Alle Druckaufträge:</h2>
|
||||||
|
<p class="size-28"><%= @jobs.size %></p>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
63
app/views/admin/jobs/_job_tr.html.erb
Normal file
63
app/views/admin/jobs/_job_tr.html.erb
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
<tr id="<%= dom_id job %>" class="bg-status-<%= job.status %>-light odd:bg-opacity-25 even:bg-opacity-10 text-hsrm-gray whitespace-nowrap hover:bg-opacity-30" data-stream-enter-class="animate-flash-increase">
|
||||||
|
<td class="p-2 py-3 text-center">
|
||||||
|
<%= link_to operator_job_path(job), target: "_top" do %>
|
||||||
|
<span class="badge badge-xl text-status-<%= job.status %> bg-status-<%= job.status %>-light">
|
||||||
|
<%= job.id %>
|
||||||
|
</span>
|
||||||
|
<% end %>
|
||||||
|
</td>
|
||||||
|
<td class="p-2 py-3">
|
||||||
|
<%= link_to_if job.customer, job.customer_firstname, ( job.customer ? admin_user_path(job.customer) : ""), target: "_top" %>
|
||||||
|
</td>
|
||||||
|
<td class="p-2 py-3">
|
||||||
|
<%= link_to_if job.customer, job.customer_lastname, ( job.customer ? admin_user_path(job.customer) : ""), target: "_top" %>
|
||||||
|
</td>
|
||||||
|
<td class="p-2 py-3">
|
||||||
|
<% if job.pdf.attached? %>
|
||||||
|
<%#= link_to job.pdf.filename, rails_blob_path(job.pdf, disposition: "attachment") %>
|
||||||
|
<%= link_to truncate(job.pdf.filename.to_s, length: 45), job.pdf, download:true, target: "_top" %>
|
||||||
|
<% if job.pdf.previewable? %>
|
||||||
|
<%= link_to job.pdf, target: "_blank", target: "_top" do %>
|
||||||
|
<span class="badge badge-hover mr-1"><%= icon("eye", class:"icon text-hsrm-gray size-6 inline") %></span>
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
||||||
|
<%= link_to job.pdf, download:true, target: "_top" do %>
|
||||||
|
<span class="badge badge-hover">
|
||||||
|
<%= icon("document-arrow-down", class: "text-hsrm-gray size-6 inline", title: "Download") %>
|
||||||
|
<%=number_to_human_size job.pdf.blob.byte_size%>
|
||||||
|
</span>
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
||||||
|
</td>
|
||||||
|
<% Job::AVAILABLE_PAGE_FORMATS.each do |din| %>
|
||||||
|
<td class="p-1 py-3">
|
||||||
|
<%= job.public_send("number_of_plans_#{din}") if job.respond_to? "number_of_plans_#{din}" %>
|
||||||
|
</td>
|
||||||
|
<% end %>
|
||||||
|
<td class="p-2 py-3 text-right">
|
||||||
|
<%= number_with_delimiter job.costum_qm_plan.round(2) %> m²
|
||||||
|
</td>
|
||||||
|
<td class="w-24 p-2 py-3 text-right">
|
||||||
|
<%= number_to_currency job.cost, locale: :de %>
|
||||||
|
</td>
|
||||||
|
<td class="p-2 py-3 text-center">
|
||||||
|
<%= l job.created_at.localtime.to_date %>
|
||||||
|
</td>
|
||||||
|
<td class="p-2 py-3 text-center">
|
||||||
|
<% if job.created_by_operator %>
|
||||||
|
<%= link_to admin_user_path(job.creator) do %>
|
||||||
|
<span class="badge badge-status">Operator</span>
|
||||||
|
<% end %>
|
||||||
|
<% else %>
|
||||||
|
<%= link_to admin_user_path(job.creator) do %>
|
||||||
|
<span class="badge badge-status badge-hover">Kunden</span>
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
<td class="p-2 py-3">
|
||||||
|
<span class="badge badge-status text-status-<%= job.status.to_sym %> bg-status-<%= job.status %>-light">
|
||||||
|
<%= job.status %>
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
58
app/views/admin/jobs/index.html.erb
Normal file
58
app/views/admin/jobs/index.html.erb
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
<% content_for :title, "Benutzerliste" %>
|
||||||
|
<h1 class="font-bold text-4xl py-4 text-hsrm-gray">Alle Druckaufträge</h1>
|
||||||
|
<% if @calendar %>
|
||||||
|
<%= link_to icon("magnifying-glass", class: "icon size-5 mr-3") + 'Filter', admin_jobs_path(), class: "px-4 py-2 hover:bg-gray-100 hover:text-hsrm-red border-b-4 hover:border-hsrm-red-light" %>
|
||||||
|
<%= content_tag :span, icon("calendar", class: "icon size-5 mr-3") + 'Kalender', class: "px-4 py-2 border-b-4 border-hsrm-red-light" %>
|
||||||
|
<div class="pt-2">
|
||||||
|
<%== pagy_nav(@calendar[:year]) %>
|
||||||
|
<%== pagy_nav(@calendar[:month]) if @calendar[:month] %>
|
||||||
|
</div>
|
||||||
|
<% else %>
|
||||||
|
<%= content_tag :span, icon("magnifying-glass", class: "icon size-5 mr-3") + 'Filter', class: "px-4 py-2 border-b-4 border-hsrm-red-light" %>
|
||||||
|
<%= link_to icon("calendar", class: "icon size-5 mr-3") + 'Kalender', admin_jobs_path(calendar: true), class: "px-4 py-2 hover:bg-gray-100 hover:text-hsrm-red border-b-4 hover:border-hsrm-red-light" %>
|
||||||
|
<div class="flex items-center justify-between py-4">
|
||||||
|
<%= search_form_for @q, data: { turbo_frame: :admin_jobs, turbo_action: 'advance' }, url: admin_jobs_path() do |f| %>
|
||||||
|
<%= f.search_field :customer_firstname_or_customer_lastname_or_pdf_blob_filename_cont, placeholder: "Suchen", oninput: 'this.form.requestSubmit();' %>
|
||||||
|
<%= f.label :status_eq, "Status:" %>
|
||||||
|
<%= f.select :status_eq, Job.statuses.keys, {include_blank: "alle"}, onchange: 'this.form.requestSubmit();' %>
|
||||||
|
<%= f.label :created_by_operator_eq, "Erstellt vom:" %>
|
||||||
|
<%= f.select :created_by_operator_eq, [["Operator", true],["Kunden", false]], {include_blank: "alle"}, onchange: 'this.form.requestSubmit();' %>
|
||||||
|
<%= f.submit "Filter anwenden", class: "py-2 px-3 bg-hsrm-red hover:bg-hsrm-red-light shadow-lg text-white inline-block font-medium cursor-pointer" %>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
||||||
|
<div>
|
||||||
|
<%= turbo_frame_tag "admin_jobs", data: { turbo_action: 'advance'} do %>
|
||||||
|
<div class="flex justify-between items-center">
|
||||||
|
<%== pagy_nav(@pagy) %>
|
||||||
|
<%== pagy_info(@pagy) %>
|
||||||
|
</div>
|
||||||
|
<div class="min-w-full overflow-auto shadow-lg pt-2">
|
||||||
|
<table class="w-full py-8 table-auto">
|
||||||
|
<thead class="font-semibold tracking-wide bg-gray-200 border-b-2 border-gray-300 text text-hsrm-gray">
|
||||||
|
<tr>
|
||||||
|
<th class="w-1 p-2 py-3 text-center text-nowrap"><%= sort_link(@q, :id, "ID", ) %></th>
|
||||||
|
<th class="min-w-24 p-2 py-3 text-left"><%= sort_link(@q, :customer_firstname, "Vorname") %></th>
|
||||||
|
<th class="min-w-24 p-2 py-3 text-left"><%= sort_link(@q, :customer_lastname, "Nachname") %></th>
|
||||||
|
<th class="p-2 py-3 text-left"><%= sort_link(@q, :pdf_blob_filename, "PDF") %></th>
|
||||||
|
<th class="w-1 p-1 py-3 text-left text-nowrap"><%= sort_link(@q, :number_of_plans_a0, "A0") %></th>
|
||||||
|
<th class="w-1 p-1 py-3 text-left text-nowrap"><%= sort_link(@q, :number_of_plans_a1, "A1") %></th>
|
||||||
|
<th class="w-1 p-1 py-3 text-left text-nowrap"><%= sort_link(@q, :number_of_plans_a2, "A2") %></th>
|
||||||
|
<th class="w-1 p-1 py-3 text-left text-nowrap"><%= sort_link(@q, :number_of_plans_a3, "A3") %></th>
|
||||||
|
<th class="w-1 p-2 py-3 text-center text-nowrap"><%= sort_link(@q, :costum_qm_plan, "no DIN") %></th>
|
||||||
|
<th class="w-1 p-2 py-3 text-center"><%= sort_link(@q, :cost, "Kosten") %></th>
|
||||||
|
<th class="w-1 p-2 py-3 text-center text-nowrap"><%= sort_link(@q, :created_at, "Erstellt am") %></th>
|
||||||
|
<th class="w-1 p-2 py-3 text-center text-nowrap"><%= sort_link(@q, :created_by_operator, "Erstellt von") %></th>
|
||||||
|
<th class="w-1 p-2 py-3 text-center"><%= sort_link(@q, :status, "Status") %></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody id='jobs' class="divide-y divivde-gray-300">
|
||||||
|
<%= render partial: "job_tr", collection: @records, as: :job, locals: { no_actions: true } %>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div class="flex justify-between items-center">
|
||||||
|
<%== pagy_nav(@pagy) %>
|
||||||
|
<%== pagy_info(@pagy, item_name: "Users") %>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
15
app/views/admin/users/_user.html.erb
Normal file
15
app/views/admin/users/_user.html.erb
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<div class="shadow bg-gray-100 p-2">
|
||||||
|
<%= icon "user", class: "size-10" %>
|
||||||
|
<p>
|
||||||
|
<%= user.name %>
|
||||||
|
<span class="badge inline"><%= user.role %></span>
|
||||||
|
</p>
|
||||||
|
<p><%= user.email %></p>
|
||||||
|
<p>E-Mail Verifiziert:
|
||||||
|
<%= icon bool_icon(user.verified), class: "icon #{user.verified ? "text-green-600" : "text-red-600"}" %></p>
|
||||||
|
<p><%= user.created_at %></p>
|
||||||
|
<p>Druckaufträge als Kunde: <%= @user.customer_jobs.size %></p>
|
||||||
|
<p>davon abgebrochen: <%= @user.customer_jobs.canceled.size %></p>
|
||||||
|
<p>Druckaufträge als Operator: <%= @user.operator_jobs.size %></p>
|
||||||
|
<p>Druckaufträge kassiert: <%= @user.cashed_jobs.size %></p>
|
||||||
|
</div>
|
||||||
45
app/views/admin/users/_user_tr.html.erb
Normal file
45
app/views/admin/users/_user_tr.html.erb
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
<tr id="<%= dom_id user %>" class="bg-role-<%= user.role %>-light odd:bg-opacity-25 even:bg-opacity-15 text-hsrm-gray whitespace-nowrap hover:bg-opacity-30"">
|
||||||
|
<td class="p-2 py-3 text-center">
|
||||||
|
<%= link_to admin_user_path(user), target: "_top" do %>
|
||||||
|
<span class="badge badge-xl text-role-<%= user.role %> bg-role-<%= user.role %>-light rounded-lg shadow">
|
||||||
|
<%= user.id %>
|
||||||
|
</span>
|
||||||
|
<% end %>
|
||||||
|
</td>
|
||||||
|
<td class="p-2 py-3">
|
||||||
|
<%= highlight(user.firstname, [ params.dig(:q, :firstname_or_lastname_or_email_cont).to_s, params.dig(:q, :firstname_cont).to_s ]) %>
|
||||||
|
<%#= user.firstname %>
|
||||||
|
</td>
|
||||||
|
<td class="p-2 py-3">
|
||||||
|
<%= highlight user.lastname, [params.dig(:q, :firstname_or_lastname_or_email_cont).to_s, params.dig(:q, :lastname_cont).to_s] %>
|
||||||
|
</td>
|
||||||
|
<td class="p-2 py-3">
|
||||||
|
<%= icon bool_icon(user.verified), class: "icon #{user.verified ? "text-green-600" : "text-red-600"}", title: "E-Mail-Adresse verifiziert" %>
|
||||||
|
<%= highlight user.email, [params.dig(:q, :firstname_or_lastname_or_email_cont).to_s, params.dig(:q, :email_start).to_s] %>
|
||||||
|
</td>
|
||||||
|
<td class="p-2 py-3 text-right">
|
||||||
|
<%= user.customer_jobs.not_canceled.size %>
|
||||||
|
</td>
|
||||||
|
<td class="p-2 py-3 text-center">
|
||||||
|
<%= l user.created_at.localtime.to_date %>
|
||||||
|
</td>
|
||||||
|
<td class="p-2 py-3 text-nowrap">
|
||||||
|
<span class="inline-flex -space-x-px overflow-hidden bg-white divide-x divide-gray-300 rounded-md shadow">
|
||||||
|
<% User.roles.keys.each do |role| %>
|
||||||
|
<% if allowed_to? :change_role?, user %>
|
||||||
|
<% if user.role == role.to_s %>
|
||||||
|
<%= button_to role, admin_user_path(user), method: :patch, params: { user: { role: role }}, form_class: "inline", class: "inline-block px-4 py-2 text-sm uppercase font-medium focus:relative bg-role-#{role}-light text-#{role}" %>
|
||||||
|
<% else %>
|
||||||
|
<%= button_to role, admin_user_path(user), method: :patch, params: { user: { role: role }}, form_class: "inline", class: "inline-block px-4 py-2 text-sm uppercase font-medium focus:relative hover:bg-role-#{role}-light text-#{role}" %>
|
||||||
|
<% end %>
|
||||||
|
<% else %>
|
||||||
|
<% if user.role == role.to_s %>
|
||||||
|
<span class="inline-block px-4 py-2 text-sm uppercase font-medium text-<%= role %> bg-role-<%= role %>-light focus:relative"><%= role %></span>
|
||||||
|
<% else %>
|
||||||
|
<span class="inline-block px-4 py-2 text-sm font-medium text-gray-400 uppercase focus:relative"><%= role %></span>
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
4
app/views/admin/users/create.html.erb
Normal file
4
app/views/admin/users/create.html.erb
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<div>
|
||||||
|
<h1 class="font-bold text-4xl">Admin::Users#create</h1>
|
||||||
|
<p>Find me in app/views/admin/users/create.html.erb</p>
|
||||||
|
</div>
|
||||||
4
app/views/admin/users/edit.html.erb
Normal file
4
app/views/admin/users/edit.html.erb
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<div>
|
||||||
|
<h1 class="font-bold text-4xl">Admin::Users#edit</h1>
|
||||||
|
<p>Find me in app/views/admin/users/edit.html.erb</p>
|
||||||
|
</div>
|
||||||
92
app/views/admin/users/index.html.erb
Normal file
92
app/views/admin/users/index.html.erb
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
<% content_for :title, "Benutzerliste" %>
|
||||||
|
<h1 class="text-4xl font-bold text-hsrm-gray">Benutzerliste</h1>
|
||||||
|
<div class="flex items-center justify-between py-4">
|
||||||
|
<!-- <div>
|
||||||
|
<div class="mt-6 md:flex md:items-center md:justify-between">
|
||||||
|
<div class="relative flex items-center mt-4 md:mt-0">
|
||||||
|
<span class="absolute">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-5 h-5 mx-3 text-gray-400 dark:text-gray-600">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" d="M21 21l-5.197-5.197m0 0A7.5 7.5 0 105.196 5.196a7.5 7.5 0 0010.607 10.607z" />
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
<input type="text" placeholder="Search" class="block w-full py-1.5 pr-5 text-gray-700 bg-white border border-gray-200 rounded-lg md:w-80 placeholder-gray-400/70 pl-11 rtl:pr-11 rtl:pl-5 dark:bg-gray-900 dark:text-gray-300 dark:border-gray-600 focus:border-blue-400 dark:focus:border-blue-300 focus:ring-blue-300 focus:outline-none focus:ring focus:ring-opacity-40">
|
||||||
|
</div>
|
||||||
|
<fieldset class="inline-flex -space-x-px overflow-hidden rounded-md border bg-white shadow-sm">
|
||||||
|
<legend class="sr-only">Color</legend>
|
||||||
|
<div>
|
||||||
|
<label for="ColorBlack" class="inline-block selecet:bg-green-500 px-4 py-2 text-sm font-medium uppercase text-gray-800 hover:bg-green-300 focus:relative">
|
||||||
|
<input type="radio" name="ColorOption" value="ColorBlack" id="ColorBlack" class="sr-only" checked />
|
||||||
|
<p class="text-sm font-medium">Alle</p>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label for="ColorBlack" class="inline-block selecet:bg-green-500 px-4 py-2 text-sm font-medium uppercase text-gray-800 hover:bg-green-300 focus:relative">
|
||||||
|
<input type="radio" name="ColorOption" value="ColorBlack" id="ColorBlack" class="sr-only" checked />
|
||||||
|
<p class="text-sm font-medium">User</p>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label for="ColorRed" class="inline-block px-4 py-2 text-sm font-medium uppercase text-gray-800 hover:bg-yellow-300 focus:relative">
|
||||||
|
<input type="radio" name="ColorOption" value="ColorRed" id="ColorRed" class="sr-only" />
|
||||||
|
<p class="text-sm font-medium">Operator</p>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label for="ColorBlue" class="inline-block px-4 py-2 text-sm font-medium uppercase text-gray-800 hover:bg-red-300 focus:relative">
|
||||||
|
<input type="radio" name="ColorOption" value="ColorBlue" id="ColorBlue" class="sr-only" />
|
||||||
|
<p class="text-sm font-medium">Admin</p>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
</div> -->
|
||||||
|
<%= search_form_for @q, data: { turbo_frame: :admin_users, turbo_action: 'advance' }, url: admin_users_path do |f| %>
|
||||||
|
<%#= f.label :firstname_cont, "Vorname:" %>
|
||||||
|
<%#= f.search_field :firstname_cont, oninput: 'this.form.requestSubmit();' %>
|
||||||
|
<%#= f.label :lastname_cont, "Nachname:" %>
|
||||||
|
<%#= f.search_field :lastname_cont, oninput: 'this.form.requestSubmit();' %>
|
||||||
|
<%#= f.label :email_start, "E-Mail:" %>
|
||||||
|
<%#= f.search_field :email_start, oninput: 'this.form.requestSubmit();' %>
|
||||||
|
<%#= f.label :firstname_or_lastname_or_email_cont, "Suchen:" %>
|
||||||
|
<%= f.search_field :firstname_or_lastname_or_email_cont, placeholder: "Suchen", oninput: 'this.form.requestSubmit();' %>
|
||||||
|
<%= f.label :created_at_dategteq, "Registriert von:" %>
|
||||||
|
<%= f.date_field :created_at_dategteq, onchange: 'this.form.requestSubmit();' %>
|
||||||
|
<%= f.label :created_at_datelteq, "bis:" %>
|
||||||
|
<%= f.date_field :created_at_datelteq, onchange: 'this.form.requestSubmit();' %>
|
||||||
|
<%= f.label :verified_eq, "E-Mail validiert:" %>
|
||||||
|
<%= f.select :verified_eq, [true,false], {include_blank: "alle"}, onchange: 'this.form.requestSubmit();' %>
|
||||||
|
<%= f.label :role_eq, "Rolle:" %>
|
||||||
|
<%#= f.collection_radio_buttons :role_eq, User::AVAILABLE_ROLES, 0,0 %>
|
||||||
|
<%= f.select :role_eq, User.roles.keys, {include_blank: "alle"}, onchange: 'this.form.requestSubmit();' %>
|
||||||
|
<%#= f. %>
|
||||||
|
<%= f.submit "Filter anwenden", class: "py-2 px-3 bg-hsrm-red hover:bg-hsrm-red-light shadow-lg text-white inline-block font-medium cursor-pointer" %>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
|
<%= turbo_frame_tag "admin_users", data: { turbo_action: 'advance'} do %>
|
||||||
|
<div class="flex justify-between items-center">
|
||||||
|
<%== pagy_nav(@pagy) %>
|
||||||
|
<%== pagy_info(@pagy) %>
|
||||||
|
</div>
|
||||||
|
<div class="min-w-full overflow-auto shadow-lg pt-2">
|
||||||
|
<table class="w-full py-8 table-auto">
|
||||||
|
<thead class="font-semibold tracking-wide bg-gray-200 border-b-2 border-gray-300 text text-hsrm-gray">
|
||||||
|
<tr>
|
||||||
|
<th class="w-1 p-2 py-3 text-center text-nowrap"><%= sort_link(@q, :id, "ID", ) %></th>
|
||||||
|
<th class="min-w-24 p-2 py-3 text-left"><%= sort_link(@q, :firstname, "Vorname") %></th>
|
||||||
|
<th class="min-w-24 p-2 py-3 text-left"><%= sort_link(@q, :lastname, "Nachname") %></th>
|
||||||
|
<th class="p-2 py-3 text-left"><%= sort_link(@q, :email, "E-Mail-Adresse") %></th>
|
||||||
|
<th class="w-1 p-2 py-3 text-right text-nowrap"><%= sort_link(@q, :customer_jobs_count, "# Jobs") %></th>
|
||||||
|
<th class="w-1 p-2 py-3 text-center text-nowrap"><%= sort_link(@q, :created_at, "Registriert am") %></th>
|
||||||
|
<th class="w-1 p-2 py-3 text-center"><%= sort_link(@q, :role, "Rolle") %></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody id='jobs' class="divide-y divivde-gray-300">
|
||||||
|
<%= render partial: "user_tr", collection: @records, as: :user %>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div class="flex justify-between items-center">
|
||||||
|
<%== pagy_nav(@pagy) %>
|
||||||
|
<%== pagy_info(@pagy, item_name: "Users") %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
4
app/views/admin/users/new.html.erb
Normal file
4
app/views/admin/users/new.html.erb
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<div>
|
||||||
|
<h1 class="font-bold text-4xl">Admin::Users#new</h1>
|
||||||
|
<p>Find me in app/views/admin/users/new.html.erb</p>
|
||||||
|
</div>
|
||||||
27
app/views/admin/users/show.html.erb
Normal file
27
app/views/admin/users/show.html.erb
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
<div>
|
||||||
|
<h1 class="text-4xl font-bold text-hsrm-gray py-4">Benutzer Details</h1>
|
||||||
|
<%= render partial: 'user', locals: { user: @user } %>
|
||||||
|
</div>
|
||||||
|
<h1 class="py-4 text-4xl font-bold text-hsrm-gray">Die letzten 10 Druckaufträge</h1>
|
||||||
|
<div class="min-w-full overflow-auto shadow-lg">
|
||||||
|
<table class="w-full py-8 table-auto">
|
||||||
|
<thead class="font-semibold tracking-wide bg-gray-200 border-b-2 border-gray-300 text text-hsrm-gray">
|
||||||
|
<tr>
|
||||||
|
<th class="w-1 p-2 py-3 text-center"> ID </th>
|
||||||
|
<th class="w-1 p-2 py-3 text-center"> Vorschau </th>
|
||||||
|
<th class="w-1 p-2 py-3 text-left"> Auftraggeber </th>
|
||||||
|
<th class="p-2 py-3 text-left"> PDF </th>
|
||||||
|
<th class="w-1 p-1 py-3 text-left"> A0 </th>
|
||||||
|
<th class="w-1 p-1 py-3 text-left"> A1 </th>
|
||||||
|
<th class="w-1 p-1 py-3 text-left"> A2 </th>
|
||||||
|
<th class="w-1 p-1 py-3 text-left"> A3 </th>
|
||||||
|
<th class="w-1 p-2 py-3 text-center text-nowrap"> no DIN </th>
|
||||||
|
<th class="w-1 p-2 py-3 text-center"> Kosten </th>
|
||||||
|
<th class="w-1 p-2 py-3 text-center"> Status </th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody id='jobs' class="divide-y divivde-gray-300">
|
||||||
|
<%= render partial: "jobs/job_tr", collection: @user.customer_jobs.order(created_at: :desc).limit(10), as: :job, locals: { no_actions: true } %>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
4
app/views/admin/users/update.html.erb
Normal file
4
app/views/admin/users/update.html.erb
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<div>
|
||||||
|
<h1 class="font-bold text-4xl">Admin::Users#update</h1>
|
||||||
|
<p>Find me in app/views/admin/users/update.html.erb</p>
|
||||||
|
</div>
|
||||||
3
app/views/jobs/_badge.html.erb
Normal file
3
app/views/jobs/_badge.html.erb
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<%= turbo_frame_tag dom_id(job, :badge) do %>
|
||||||
|
<%= link_to_if user_signed_in? && allowed_to?(:show, job, namespace: :Operator), job.id, operator_job_path(job), target: "_blank" %>
|
||||||
|
<% end %>
|
||||||
28
app/views/jobs/_cancel_button.html.erb
Normal file
28
app/views/jobs/_cancel_button.html.erb
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
<%= turbo_frame_tag dom_id(job, :cancel_button) do %>
|
||||||
|
<%# TODO: Refactor! %>
|
||||||
|
<% if user_signed_in? %>
|
||||||
|
<% if allowed_to? :cancel?, job %>
|
||||||
|
<%= button_to icon("x-circle", class: "icon size-10 text-hsrm-red", title: "Druckauftrag abbrechen (Anmeldung erforderlich)"), cancel_job_path(job), method: :patch, target: "_top", form: {data: {turbo_frame: "_top", turbo_confirm: 'Den Plottauftrag wirklich abbrechen?'}}, form_class: "inline" %>
|
||||||
|
<% else %>
|
||||||
|
<% if job.open? %>
|
||||||
|
<% if job.created_by_operator %>
|
||||||
|
<%= icon("x-circle", class: "icon icon-disabled size-10", title: "Druckauftrag kann nur vom Operator abgebrochen werden!") %>
|
||||||
|
<% else %>
|
||||||
|
<%= icon("x-circle", class: "icon icon-disabled size-10", title: "Sie sind nicht berechtigt diesen Druckauftrag abzubrechen") %>
|
||||||
|
<% end %>
|
||||||
|
<% else %>
|
||||||
|
<%= icon("x-circle", class: "icon icon-disabled size-10", title: "Kann nicht mehr abgebrochen werden") %>
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
||||||
|
<% else %>
|
||||||
|
<% if job.open? %>
|
||||||
|
<% if job.created_by_operator %>
|
||||||
|
<%= icon("x-circle", class: "icon icon-disabled size-10", title: "Druckauftrag kann nur vom Operator abgebrochen werden!") %>
|
||||||
|
<% else %>
|
||||||
|
<%= button_to icon("x-circle", class: "icon size-10 text-hsrm-red", title: "Druckauftrag abbrechen (Anmeldung erforderlich)"), cancel_job_path(job), method: :patch, form: {data: {turbo_frame: "_top", turbo_confirm: 'Den Plottauftrag wirklich abbrechen? (Anmeldung erforderlich!)'}}, form_class: "inline" %>
|
||||||
|
<% end %>
|
||||||
|
<% else %>
|
||||||
|
<%= icon("x-circle", class: "icon icon-disabled size-10", title: "Kann nicht mehr abgebrochen werden") %>
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
||||||
@@ -11,19 +11,19 @@
|
|||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
<div class="my-5">
|
<div class="my-5">
|
||||||
<%= form.label :costumer_firstname, 'Vorname' %>
|
<%= form.label :customer_firstname, 'Vorname' %>
|
||||||
<%= form.text_field :costumer_firstname, class: "block shadow-lg rounded-md border border-hsrm-gray outline-none px-3 py-2 mt-2 w-full" %>
|
<%= form.text_field :customer_firstname, disabled: true ,class: "block shadow-lg rounded-md border border-hsrm-gray outline-none px-3 py-2 mt-2 w-full" %>
|
||||||
</div>
|
</div>
|
||||||
<div class="my-5">
|
<div class="my-5">
|
||||||
<%= form.label :costumer_lastname, 'Nachname' %>
|
<%= form.label :customer_lastname, 'Nachname' %>
|
||||||
<%= form.text_field :costumer_lastname, class: "block shadow-lg rounded-md border border-hsrm-gray outline-none px-3 py-2 mt-2 w-full" %>
|
<%= form.text_field :customer_lastname, disabled: true ,class: "block shadow-lg rounded-md border border-hsrm-gray outline-none px-3 py-2 mt-2 w-full" %>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<%= form.label :pdf, "Plan auswählen (PDF-Format)" %>
|
<%= form.label :pdf, "Plan auswählen (PDF-Format)" %>
|
||||||
<%= form.file_field :pdf, accept: "application/pdf", class: "block shadow-lg rounded-md border border-hsrm-gray outline-none px-3 py-2 mt-2 w-full" %>
|
<%= form.file_field :pdf, accept: "application/pdf", required: true, class: "block shadow-lg rounded-md border border-hsrm-gray outline-none px-3 py-2 mt-2 w-full" %>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<%= form.check_box :privacy_policy_accepted, class: "mt-2 h-5 w-5" %> <%= form.label :privacy_policy_accepted, "Datenschutzerklärung akzeptiert", class: "p-2" %>
|
<%= form.check_box :privacy_policy, required: true, class: "mt-2 h-5 w-5" %> <%= form.label :privacy_policy, "Datenschutzerklärung akzeptiert", class: "p-2" %>
|
||||||
</div>
|
</div>
|
||||||
<div class="inline">
|
<div class="inline">
|
||||||
<%= form.submit "Plottauftrag abschicken", class: "py-2 px-3 bg-hsrm-red hover:bg-hsrm-red-light shadow-lg text-white inline-block font-medium cursor-pointer" %>
|
<%= form.submit "Plottauftrag abschicken", class: "py-2 px-3 bg-hsrm-red hover:bg-hsrm-red-light shadow-lg text-white inline-block font-medium cursor-pointer" %>
|
||||||
|
|||||||
@@ -1,17 +1,26 @@
|
|||||||
<tr id="<%= dom_id job %>" class="bg-status-<%= job.status %>-light odd:bg-opacity-20 even:bg-opacity-15 text-hsrm-gray whitespace-nowrap hover:bg-opacity-30">
|
<tr id="<%= dom_id job %>" class="bg-status-<%= job.status %>-light odd:bg-opacity-25 even:bg-opacity-15 text-hsrm-gray whitespace-nowrap hover:bg-opacity-30" data-stream-enter-class="animate-flash-increase">
|
||||||
<td class="p-2 py-3 text-center">
|
<td class="p-2 py-3 text-center">
|
||||||
<span class="badge badge-xl text-status-<%= job.status %> bg-status-<%= job.status %>-light rounded-lg shadow">
|
<span class="badge badge-xl text-status-<%= job.status %> bg-status-<%= job.status %>-light rounded-lg shadow">
|
||||||
<%= job.id %>
|
<% # TODO: Refactor to helper function %>
|
||||||
|
<% if defined?(no_turbo_stream) && no_turbo_stream %>
|
||||||
|
<%= turbo_frame_tag dom_id(job, :badge) do %>
|
||||||
|
<%= render partial: "jobs/badge", locals: { job: job } %>
|
||||||
|
<% end %>
|
||||||
|
<% else %>
|
||||||
|
<%= turbo_frame_tag dom_id(job, :badge), src: badge_job_path(job), loading: 'lazy' do %>
|
||||||
|
<%= icon("ellipsis-horizontal-circle", class: "icon icon-disabled size-10", title: "Loading...") %>
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
<td class="p-2 py-3 text-center">
|
<td class="p-2 py-3 text-center">
|
||||||
<% if job.pdf.attached? %>
|
<% if job.pdf.attached? && job.pdf.previewable? %>
|
||||||
<%= image_tag(url_for(job.pdf.blob.preview(resize_to_limit: [100, 100])), class: "shadow") %>
|
<%= image_tag(url_for(job.pdf.blob.preview(resize_to_limit: [100, 100])), class: "shadow") %>
|
||||||
<%#= image_tag job.pdf.preview(resize_to_limit: [50, 50]), class: "mx-auto" %>
|
<%# = image_tag job.pdf.preview(resize_to_limit: [50, 50]), class: "mx-auto" %>
|
||||||
<% end %>
|
<% end %>
|
||||||
</td>
|
</td>
|
||||||
<td class="p-2 py-3">
|
<td class="p-2 py-3">
|
||||||
<%= job.costumer_fullname %>
|
<%= job.customer_fullname %>
|
||||||
</td>
|
</td>
|
||||||
<td class="p-2 py-3">
|
<td class="p-2 py-3">
|
||||||
<% if job.pdf.attached? %>
|
<% if job.pdf.attached? %>
|
||||||
@@ -40,12 +49,12 @@
|
|||||||
</td>
|
</td>
|
||||||
<td class="p-2 py-3 text-right">
|
<td class="p-2 py-3 text-right">
|
||||||
<span class="badge">
|
<span class="badge">
|
||||||
<%= job.costum_qm_plan.round(2) %> m²
|
<%= number_with_delimiter job.costum_qm_plan.round(2) %> m²
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
<td class="w-24 p-2 py-3 text-right">
|
<td class="w-24 p-2 py-3 text-right">
|
||||||
<span class="badge">
|
<span class="badge">
|
||||||
<%= job.cost.round(2) %> €
|
<%= number_to_currency job.cost, locale: :de %>
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
<td class="p-2 py-3">
|
<td class="p-2 py-3">
|
||||||
@@ -53,11 +62,18 @@
|
|||||||
<%= job.status %>
|
<%= job.status %>
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
<td class="p-2 py-3 text-right">
|
<% unless defined?(no_actions) && no_actions %>
|
||||||
<% if job.open? %>
|
<td class="p-2 py-3 text-right">
|
||||||
<%= button_to icon("x-circle", class: "icon size-10 text-hsrm-red", title: "Abbrechen"), cancel_job_path(job), method: :patch, form: {data: {turbo_confirm: 'Den Plottauftrag wirklich abbrechen?'}}, form_class: "inline" %>
|
<% # TODO: Refactor to helper function %>
|
||||||
<% else %>
|
<% if defined?(no_turbo_stream) && no_turbo_stream %>
|
||||||
<%= icon("x-circle", class: "icon icon-disabled size-10", title: "Kann nicht mehr abgebrochen werden") %>
|
<%= turbo_frame_tag dom_id(job, :cancel_button) do %>
|
||||||
|
<%= render partial: "jobs/cancel_button", locals: { job: job } %>
|
||||||
|
<% end %>
|
||||||
|
<% else %>
|
||||||
|
<%= turbo_frame_tag dom_id(job, :cancel_button), src: cancel_button_job_path(job), loading: 'lazy' do %>
|
||||||
|
<%= icon("ellipsis-horizontal-circle", class: "icon icon-disabled size-10", title: "Loading...") %>
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
||||||
<% end %>
|
<% end %>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
<%= turbo_stream_from 'jobs' %>
|
<%= turbo_stream_from 'jobs' %>
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<%#= render partial: 'layouts/flash' %>
|
|
||||||
<% content_for :title, "Current Print Jobs" %>
|
<% content_for :title, "Current Print Jobs" %>
|
||||||
<div class="flex items-center justify-between py-4">
|
<div class="flex items-center justify-between py-4">
|
||||||
<h1 class="text-4xl font-bold text-hsrm-gray">Aktuelle Plottaufträge <span class="text-sm font-semibold"><%= Date.today.strftime("%d.%m.%Y") %></span></h1>
|
<h1 class="text-4xl font-bold text-hsrm-gray">Aktuelle Druckaufträge <span class="text-sm font-semibold"><%= Date.today.strftime("%d.%m.%Y") %></span></h1>
|
||||||
<%= link_to "Plottauftrag aufgeben", new_job_path, class: "px-3 py-2 bg-hsrm-red drop-shadow-lg transition-colors hover:bg-hsrm-red-light text-white block font-medium" %>
|
<%= link_to "Plottauftrag aufgeben", new_job_path, class: "px-3 py-2 bg-hsrm-red drop-shadow-lg transition-colors hover:bg-hsrm-red-light text-white block font-medium" %>
|
||||||
</div>
|
</div>
|
||||||
<div class="min-w-full overflow-auto shadow-lg">
|
<div class="min-w-full overflow-auto shadow-lg">
|
||||||
@@ -24,9 +23,8 @@
|
|||||||
<th class="w-1 p-2 py-3 text-center">Action</th>
|
<th class="w-1 p-2 py-3 text-center">Action</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody id='jobs' class="divide-y divivde-gray-300">
|
<tbody id="jobs" class="divide-y divivde-gray-300">
|
||||||
<%= render partial: "job_tr", collection: @jobs, as: :job %>
|
<%= render partial: "job_tr", collection: @jobs, as: :job, locals: { no_turbo_stream: @no_turbo_stream } %>
|
||||||
<%#= link_to "Show this job", job, class: "ml-2 rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium" %>
|
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<div class="mx-auto md:w-2/3 w-full">
|
<div class="mx-auto md:w-2/3 w-full">
|
||||||
<h1 class="font-bold text-4xl">Plottauftrag erteillen</h1>
|
<h1 class="font-bold text-4xl">Druckauftrag aufgeben</h1>
|
||||||
<%= render "form", job: @job %>
|
<%= render "form", job: @job %>
|
||||||
<%= link_to "Zurück zur Übersicht", jobs_path, class: "ml-2 rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium" %>
|
<%= link_to "Zurück zur Übersicht", jobs_path, class: "ml-2 rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium" %>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
23
app/views/layouts/_back_to_top.html.erb
Normal file
23
app/views/layouts/_back_to_top.html.erb
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<!-- Back to top button -->
|
||||||
|
<%= link_to "#", class: "opacity-80" do %>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
data-twe-ripple-init
|
||||||
|
data-twe-ripple-color="light"
|
||||||
|
class="!fixed bottom-5 end-5 rounded-full bg-hsrm-red p-3 text-xs font-medium uppercase leading-tight text-white shadow-md transition duration-150 ease-in-out hover:bg-hsrm-red-light hover:shadow-lg focus:bg-hsrm-red-light focus:shadow-lg focus:outline-none focus:ring-0 active:bg-hsrm-red-light active:shadow-lg"
|
||||||
|
id="btn-back-to-top">
|
||||||
|
<span class="[&>svg]:w-4">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
fill="none"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
stroke-width="3"
|
||||||
|
stroke="currentColor">
|
||||||
|
<path
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
d="M4.5 10.5 12 3m0 0 7.5 7.5M12 3v18" />
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
<% end %>
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
<%= turbo_frame_tag "flash" do %>
|
<%= turbo_frame_tag "flash" do %>
|
||||||
<% flash.each do |type, message| %>
|
<% flash.each do |type, message| %>
|
||||||
<div data-controller="flash" data-flash-target="toast" class="fixed z-50 top-2 right-2 border p-3 shadow-lg opacity-100 translate-x-full transition-transform ease-in-out duration-300 transform <%= type == :alert ? "bg-red-50 border-red-500/50 text-red-800" : "bg-green-50 border-green-300/90 text-green-800" %>">
|
<div data-controller="flash" data-flash-target="toast" class="fixed z-50 top-2 right-2 border p-3 shadow-lg opacity-100 translate-x-full transition-transform ease-in-out duration-300 transform <%= type == "alert" ? "bg-red-50 border-red-500/50 text-red-800" : "bg-green-50 border-green-300/90 text-green-800" %>">
|
||||||
<div class="flex items-center justify-between gap-4">
|
<div class="flex items-center justify-between gap-4">
|
||||||
<%= icon "check", class: "size-4 stroke-primary-500" %>
|
<%= icon "check", class: "size-4 stroke-primary-500" %>
|
||||||
<span class="text-l"><%= message %></span>
|
<span class="text-l"><%= message %></span>
|
||||||
|
|||||||
@@ -1,21 +1,35 @@
|
|||||||
<header class="container flex items-center justify-between px-4 py-6 mx-auto border-b-2 border-gray-300">
|
<header class="container bg-white sticky z-10 top-0 flex items-center justify-between px-4 py-6 mx-auto border-b-2 border-gray-300">
|
||||||
<a href="/" class="text-4xl font-bold text-hsrm-gray">Plottservice Fachbereich AB</a>
|
<a href="/" class="text-4xl font-bold text-hsrm-gray">Plottservice FAB</a>
|
||||||
<% if user_signed_in? && current_user.admin? || current_user.operator? %>
|
<nav>
|
||||||
<nav>
|
<ul class="flex justify-center space-x-2 font-semibold items-color">
|
||||||
<ul class="flex justify-center font-semibold items-color">
|
<li class="relative">
|
||||||
|
<button class="px-4 py-2 hover:text-hsrm-red border-b-4 <%= root_tab? && 'border-hsrm-red-light' || 'hover:border-hsrm-red-light hover:bg-gray-100' %>">
|
||||||
|
<%= link_to "Aktuelle Druckaufträge", root_path %>
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
<% if user_signed_in? %>
|
||||||
<li class="relative">
|
<li class="relative">
|
||||||
<button class="px-4 py-2 cursor-default hover:text-hsrm-red">
|
<button class="px-4 py-2 hover:text-hsrm-red border-b-4 <%= profile_tab? && 'border-hsrm-red-light' || 'hover:border-hsrm-red-light hover:bg-gray-100' %>">
|
||||||
<%= link_to_if current_user.admin?, "Admin", admin_dashboard_path %>
|
<%= link_to "Profil", profile_path %>
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
<li class="relative">
|
<% if allowed_to? :admin?, with: ApplicationPolicy %>
|
||||||
<button class="px-4 py-2 cursor-default hover:text-hsrm-red">
|
<li class="relative">
|
||||||
<%= link_to 'Operator', operator_jobs_path %>
|
<button class="px-4 py-2 <%= current_user.admin? && 'hover:text-hsrm-red' || 'text-hsrm-gray-light' %> border-b-4 <%= admin_tab? && 'border-hsrm-red-light' || 'hover:border-hsrm-red-light hover:bg-gray-100' %>">
|
||||||
</button>
|
<%= link_to_if current_user.admin?, "Admin", admin_dashboard_path %>
|
||||||
</li>
|
</button>
|
||||||
</ul>
|
</li>
|
||||||
</nav>
|
<% end %>
|
||||||
<% end %>
|
<% if allowed_to? :operate?, with: ApplicationPolicy %>
|
||||||
|
<li class="relative">
|
||||||
|
<button class="px-4 py-2 hover:text-hsrm-red border-b-4 <%= operator_tab? && 'border-hsrm-red-light' || 'hover:border-hsrm-red-light hover:bg-gray-100' %>">
|
||||||
|
<%= link_to 'Operator', operator_jobs_path %>
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
<nav>
|
<nav>
|
||||||
<ul class="flex items-center">
|
<ul class="flex items-center">
|
||||||
<% if user_signed_in? %>
|
<% if user_signed_in? %>
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
<body class="bg-white">
|
<body class="bg-white">
|
||||||
<%= render "layouts/flash" %>
|
<%= render "layouts/flash" %>
|
||||||
<%= render "layouts/header" %>
|
<%= render "layouts/header" %>
|
||||||
|
<%= render "layouts/back_to_top" %>
|
||||||
<main class="container px-4 mx-auto mt-4">
|
<main class="container px-4 mx-auto mt-4">
|
||||||
<%= yield %>
|
<%= yield %>
|
||||||
</main>
|
</main>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<%= form_with(model: job, class: "contents") do |form| %>
|
<%= form_with(model: [:operator, job], class: "contents") do |form| %>
|
||||||
<% if job.errors.any? %>
|
<% if job.errors.any? %>
|
||||||
<div id="error_explanation" class="bg-red-50 text-red-500 px-3 py-2 font-medium rounded-lg shadow-lg border-l border-red mt-3" >
|
<div id="error_explanation" class="px-3 py-2 mt-3 font-medium text-red-500 border-l rounded-lg shadow-lg bg-red-50 border-red" >
|
||||||
<h2><%= pluralize(job.errors.count, "error") %>
|
<h2><%= pluralize(job.errors.count, "error") %>
|
||||||
prohibited this job from being saved:</h2>
|
prohibited this job from being saved:</h2>
|
||||||
<ul>
|
<ul>
|
||||||
@@ -11,45 +11,49 @@
|
|||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
<div class="my-5">
|
<div class="my-5">
|
||||||
<%= form.label :costumer_firstname, 'Vorname' %>
|
<%= form.label :customer_firstname, 'Vorname' %>
|
||||||
<%= form.text_field :costumer_firstname, class: "block shadow-lg rounded-md border border-hsrm-gray outline-none px-3 py-2 mt-2 w-full" %>
|
<%= form.text_field :customer_firstname, class: "block shadow-lg rounded-md border border-hsrm-gray outline-none px-3 py-2 mt-2 w-full" %>
|
||||||
</div>
|
</div>
|
||||||
<div class="my-5">
|
<div class="my-5">
|
||||||
<%= form.label :costumer_lastname, 'Nachname' %>
|
<%= form.label :customer_lastname, 'Nachname' %>
|
||||||
<%= form.text_field :costumer_lastname, class: "block shadow-lg rounded-md border border-hsrm-gray outline-none px-3 py-2 mt-2 w-full" %>
|
<%= form.text_field :customer_lastname, class: "block shadow-lg rounded-md border border-hsrm-gray outline-none px-3 py-2 mt-2 w-full" %>
|
||||||
</div>
|
</div>
|
||||||
<!-- <div class="my-5"> -->
|
<div class="my-5 inline">
|
||||||
<!-- <%= form.label :intern %> -->
|
<%= form.check_box :intern, class: "pr-2 h-5 w-5" %>
|
||||||
<!-- <%= form.check_box :intern, class: "block mt-2 h-5 w-5" %> -->
|
<%= form.label :intern, "Interne Umbuchung" %>
|
||||||
<!-- </div> -->
|
|
||||||
<!-- <div class="my-5"> -->
|
|
||||||
<!-- <%= form.label :cost_center %> -->
|
|
||||||
<!-- <%= form.text_field :cost_center, class: "block shadow-lg rounded-md border border-hsrm-gray outline-none px-3 py-2 mt-2 w-full" %> -->
|
|
||||||
<!-- </div> -->
|
|
||||||
<!-- <div class="my-5"> -->
|
|
||||||
<!-- <%= form.label :number_of_plans_a0 %> -->
|
|
||||||
<!-- <%= form.number_field :number_of_plans_a0, class: "block shadow-lg rounded-md border border-hsrm-gray outline-none px-3 py-2 mt-2 w-full" %> -->
|
|
||||||
<!-- </div> -->
|
|
||||||
<!-- <div class="my-5"> -->
|
|
||||||
<!-- <%= form.label :number_of_plans_a1 %> -->
|
|
||||||
<!-- <%= form.number_field :number_of_plans_a1, class: "block shadow-lg rounded-md border border-hsrm-gray outline-none px-3 py-2 mt-2 w-full" %> -->
|
|
||||||
<!-- </div> -->
|
|
||||||
<!-- <div class="my-5"> -->
|
|
||||||
<!-- <%= form.label :number_of_plans_a2 %> -->
|
|
||||||
<!-- <%= form.number_field :number_of_plans_a2, class: "block shadow-lg rounded-md border border-hsrm-gray outline-none px-3 py-2 mt-2 w-full" %> -->
|
|
||||||
<!-- </div> -->
|
|
||||||
<!-- <div class="my-5"> -->
|
|
||||||
<!-- <%= form.label :number_of_plans_a3 %> -->
|
|
||||||
<!-- <%= form.number_field :number_of_plans_a3, class: "block shadow-lg rounded-md border border-hsrm-gray outline-none px-3 py-2 mt-2 w-full" %> -->
|
|
||||||
<!-- </div> -->
|
|
||||||
<div>
|
|
||||||
<%= form.label :pdf, "Plan auswählen (PDF-Format)" %>
|
|
||||||
<%= form.file_field :pdf, accept: "application/pdf", class: "block shadow-lg rounded-md border border-hsrm-gray outline-none px-3 py-2 mt-2 w-full" %>
|
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div class="my-5">
|
||||||
<%= form.check_box :privacy_policy_accepted, class: "mt-2 h-5 w-5" %> <%= form.label :privacy_policy_accepted, "Datenschutzerklärung akzeptiert", class: "p-2" %>
|
<%= form.label :cost_center, "Kostenstelle/Auftragsnummer" %>
|
||||||
|
<%= form.text_field :cost_center, class: "block shadow-lg rounded-md border border-hsrm-gray outline-none px-3 py-2 mt-2 w-full" %>
|
||||||
</div>
|
</div>
|
||||||
|
<% if edit_form? %>
|
||||||
|
<div class="my-5">
|
||||||
|
<%= form.label :number_of_plans_a0, "Anzahl A0 Pläne" %>
|
||||||
|
<%= form.number_field :number_of_plans_a0, class: "block shadow-lg rounded-md border border-hsrm-gray outline-none px-3 py-2 mt-2 w-full" %>
|
||||||
|
</div>
|
||||||
|
<div class="my-5">
|
||||||
|
<%= form.label :number_of_plans_a1, "Anzahl A1 Pläne" %>
|
||||||
|
<%= form.number_field :number_of_plans_a1, class: "block shadow-lg rounded-md border border-hsrm-gray outline-none px-3 py-2 mt-2 w-full" %>
|
||||||
|
</div>
|
||||||
|
<div class="my-5">
|
||||||
|
<%= form.label :number_of_plans_a2, "Anzahl A2 Pläne" %>
|
||||||
|
<%= form.number_field :number_of_plans_a2, class: "block shadow-lg rounded-md border border-hsrm-gray outline-none px-3 py-2 mt-2 w-full" %>
|
||||||
|
</div>
|
||||||
|
<div class="my-5">
|
||||||
|
<%= form.label :number_of_plans_a3, "Anzahl A3 Pläne" %>
|
||||||
|
<%= form.number_field :number_of_plans_a3, class: "block shadow-lg rounded-md border border-hsrm-gray outline-none px-3 py-2 mt-2 w-full" %>
|
||||||
|
</div>
|
||||||
|
<div class="my-5">
|
||||||
|
<%= form.label :costum_qm_plan, "Quatratmeter noDin" %>
|
||||||
|
<%= form.number_field :costum_qm_plan, in: 0..20.0, step: 0.01 ,class: "block shadow-lg rounded-md border border-hsrm-gray outline-none px-3 py-2 mt-2 w-full" %>
|
||||||
|
</div>
|
||||||
|
<% else %>
|
||||||
|
<div>
|
||||||
|
<%= form.label :pdf, "Plan auswählen (PDF-Format)" %>
|
||||||
|
<%= form.file_field :pdf, accept: "application/pdf", class: "block shadow-lg rounded-md border border-hsrm-gray outline-none px-3 py-2 mt-2 w-full" %>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
<div class="inline">
|
<div class="inline">
|
||||||
<%= form.submit "Plottauftrag abschicken", class: "py-2 px-3 bg-hsrm-red hover:bg-hsrm-red-light shadow-lg text-white inline-block font-medium cursor-pointer" %>
|
<%= form.submit edit_form? && "Speichern" || "Druckauftrag anlegen", class: "py-2 px-3 bg-hsrm-red hover:bg-hsrm-red-light shadow-lg text-white inline-block font-medium cursor-pointer" %>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|||||||
@@ -1,64 +1,103 @@
|
|||||||
<div id="<%= dom_id job %>">
|
<div id="<%= dom_id job %>" class="flex flex-row space-x-4 shadow">
|
||||||
<iframe src=<%= url_for(@job.pdf) %>
|
<div>
|
||||||
width="700" height="780" style="border: none;"></iframe>
|
<% if @job.pdf.attached? && job.pdf.previewable? %>
|
||||||
<p class="my-5">
|
<embed type="application/pdf" src="<%= url_for(@job.pdf) %>" width="600px" height="800px" class="" />
|
||||||
<strong class="block font-medium mb-1">Operator:</strong>
|
<% end %>
|
||||||
<%= job.operator_id %>
|
</div>
|
||||||
</p>
|
<div>
|
||||||
<p class="my-5">
|
<p class="my-3">
|
||||||
<strong class="block font-medium mb-1">Costumer:</strong>
|
<strong class="mb-1 font-medium">customer ID:</strong>
|
||||||
<%= job.costumer_id %>
|
<% if job.customer %>
|
||||||
</p>
|
<%= link_to_if allowed_to?(:show?, job.customer, namespace: :Admin), "#{job.customer_id} - #{job.customer.name} (#{job.customer.email})", admin_user_path(job.customer) %>
|
||||||
<p class="my-5">
|
<% else %>
|
||||||
<strong class="block font-medium mb-1">Operator firstname:</strong>
|
-
|
||||||
<%= job.operator_firstname %>
|
<% end %>
|
||||||
</p>
|
</p>
|
||||||
<p class="my-5">
|
<p class="my-3">
|
||||||
<strong class="block font-medium mb-1">Operator lastname:</strong>
|
<strong class="mb-1 font-medium">Creator ID:</strong>
|
||||||
<%= job.operator_lastname %>
|
<% if job.creator %>
|
||||||
</p>
|
<%= link_to_if allowed_to?(:show?, job.creator, namespace: :Admin, ), "#{job.creator_id} - #{job.creator.name} (#{job.creator.email})", admin_user_path(job.creator) %>
|
||||||
<p class="my-5">
|
<% else %>
|
||||||
<strong class="block font-medium mb-1">Costumer firstname:</strong>
|
-
|
||||||
<%= job.costumer_firstname %>
|
<% end %>
|
||||||
</p>
|
</p>
|
||||||
<p class="my-5">
|
<p class="my-3">
|
||||||
<strong class="block font-medium mb-1">Costumer lastname:</strong>
|
<strong class="mb-1 font-medium">Operator ID:</strong>
|
||||||
<%= job.costumer_lastname %>
|
<% if job.operator %>
|
||||||
</p>
|
<%= link_to_if allowed_to?(:show?, job.operator, namespace: :Admin), "#{job.operator_id} - #{job.operator.name} (#{job.operator.email})", admin_user_path(job.operator) %>
|
||||||
<p class="my-5">
|
<% else %>
|
||||||
<strong class="block font-medium mb-1">Paid:</strong>
|
-
|
||||||
<%= job.paid %>
|
<% end %>
|
||||||
</p>
|
</p>
|
||||||
<p class="my-5">
|
<p class="my-3">
|
||||||
<strong class="block font-medium mb-1">Printed at:</strong>
|
<strong class="mb-1 font-medium">Cashier ID:</strong>
|
||||||
<%= job.printed_at %>
|
<% if job.cashier %>
|
||||||
</p>
|
<%= link_to_if allowed_to?(:show?, job.cashier, namespace: :Admin), "#{job.cashier_id} - #{job.cashier.name} (#{job.cashier.email})", admin_user_path(job.cashier) %>
|
||||||
<p class="my-5">
|
<% else %>
|
||||||
<strong class="block font-medium mb-1">Intern:</strong>
|
-
|
||||||
<%= job.intern %>
|
<% end %>
|
||||||
</p>
|
</p>
|
||||||
<p class="my-5">
|
<p class="my-3">
|
||||||
<strong class="block font-medium mb-1">Cost center:</strong>
|
<strong class="mb-1 font-medium">Kunde:</strong>
|
||||||
<%= job.cost_center %>
|
<%= link_to_if job.customer && allowed_to?(:show? , job.customer, namespace: :Admin), "#{job.customer_firstname} #{job.customer_lastname}", ( job.customer ? admin_user_path(job.customer) : "" ) %>
|
||||||
</p>
|
</p>
|
||||||
<p class="my-5">
|
<p class="my-3">
|
||||||
<strong class="block font-medium mb-1">Number of plans a0:</strong>
|
<strong class="mb-1 font-medium">Operator:</strong>
|
||||||
<%= job.number_of_plans_a0 %>
|
<%= link_to_if job.operator && allowed_to?(:show, job.operator, namespace: :Admin), "#{job.operator_firstname} #{job.operator_lastname}", ( job.operator ? admin_users_path(job.operator) : "" )%>
|
||||||
</p>
|
</p>
|
||||||
<p class="my-5">
|
<p class="my-3">
|
||||||
<strong class="block font-medium mb-1">Number of plans a1:</strong>
|
<strong class="mb-1 font-medium">Kassierer:</strong>
|
||||||
<%= job.number_of_plans_a1 %>
|
<%= link_to_if job.cashier && allowed_to?(:show, job.cashier, namespace: :Admin), "#{job.cashier_firstname} #{job.cashier_lastname}", ( job.cashier ? admin_users_path(job.cashier) : "" ) %>
|
||||||
</p>
|
</p>
|
||||||
<p class="my-5">
|
<p class="my-3">
|
||||||
<strong class="block font-medium mb-1">Number of plans a2:</strong>
|
<strong class="mb-1 font-medium">Erstellt durch Operator:</strong>
|
||||||
<%= job.number_of_plans_a2 %>
|
<%= icon bool_icon(job.created_by_operator), class: "icon #{job.created_by_operator ? "text-green-600" : "text-red-600"}" %>
|
||||||
</p>
|
</p>
|
||||||
<p class="my-5">
|
<p class="my-3">
|
||||||
<strong class="block font-medium mb-1">Number of plans a3:</strong>
|
<strong class="mb-1 font-medium">Aktueller Status:</strong>
|
||||||
<%= job.number_of_plans_a3 %>
|
<span class="badge badge-status inline text-status-<%= job.status.to_sym %> bg-status-<%= job.status %>-light">
|
||||||
</p>
|
<%= job.status %>
|
||||||
<p class="my-5">
|
</span>
|
||||||
<strong class="block font-medium mb-1">Costum qm plan:</strong>
|
</p>
|
||||||
<%= job.costum_qm_plan %>
|
<p class="my-3">
|
||||||
</p>
|
<strong class="mb-1 font-medium">Paid at:</strong>
|
||||||
</div>
|
<%= job.paid_at %>
|
||||||
|
</p>
|
||||||
|
<p class="my-3">
|
||||||
|
<strong class="mb-1 font-medium">Printed at:</strong>
|
||||||
|
<%= job.printed_at %>
|
||||||
|
</p>
|
||||||
|
<p class="my-3">
|
||||||
|
<strong class="mb-1 font-medium">Interne Umbuchung:</strong>
|
||||||
|
<%= icon bool_icon(job.intern), class: "icon #{job.intern ? "text-green-600" : "text-red-600"}" %>
|
||||||
|
</p>
|
||||||
|
<p class="my-3">
|
||||||
|
<strong class="mb-1 font-medium">Kostenstelle:</strong>
|
||||||
|
<%= job.cost_center %>
|
||||||
|
</p>
|
||||||
|
<p class="my-3">
|
||||||
|
<strong class="block mb-1 font-medium">Plans:
|
||||||
|
<table class="text-center">
|
||||||
|
<tr class="p-2 bg-gray-300">
|
||||||
|
<th class="p-2">a0</th>
|
||||||
|
<th class="p-2">a1</th>
|
||||||
|
<th class="p-2">a2</th>
|
||||||
|
<th class="p-2">a3</th>
|
||||||
|
<th class="p-2">costum</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><%= job.number_of_plans_a0 %></td>
|
||||||
|
<td><%= job.number_of_plans_a1 %></td>
|
||||||
|
<td><%= job.number_of_plans_a2 %></td>
|
||||||
|
<td><%= job.number_of_plans_a3 %></td>
|
||||||
|
<td><%= job.costum_qm_plan %> qm</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</p>
|
||||||
|
<%= link_to "Edit this job", edit_operator_job_path(@job), class: "btn" %>
|
||||||
|
<%= link_to "Back to jobs", operator_jobs_path, class: "btn" %>
|
||||||
|
<div class="inline-block">
|
||||||
|
<%= button_to "Destroy this job", operator_job_path(@job), method: :delete, class: "btn btn-alert inline-block" %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<h3 class="p-3 text-2xl font-bold">
|
<h3 class="p-3 text-2xl font-bold">
|
||||||
<%= icon(status_icon(status), class: "text-status-#{status} icon icon-nohover") %>
|
<%= icon(status_icon(status), class: "text-status-#{status} icon icon-nohover") %>
|
||||||
<%= status %>
|
<%= status %>
|
||||||
<span class="block text-3xl text-right"><%= jobs.count %></span>
|
<span class="block text-3xl text-right"><%= jobs.size %></span>
|
||||||
</h3>
|
</h3>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|||||||
@@ -1,55 +1,69 @@
|
|||||||
<tr id="<%= dom_id job %>" class="bg-status-<%= job.status %>-light odd:bg-opacity-20 even:bg-opacity-10 text-hsrm-gray whitespace-nowrap hover:bg-opacity-30">
|
<tr id="<%= dom_id job %>" class="bg-status-<%= job.status %>-light odd:bg-opacity-25 even:bg-opacity-10 text-hsrm-gray whitespace-nowrap hover:bg-opacity-30" data-stream-enter-class="animate-flash-increase">
|
||||||
<td class="p-2 py-3 text-center">
|
<td class="p-2 py-3 text-center">
|
||||||
<span class="badge badge-xl text-status-<%= job.status %> bg-status-<%= job.status %>-light">
|
<%= link_to operator_job_path(job) do %>
|
||||||
<%= job.id %>
|
<span class="badge badge-xl text-status-<%= job.status %> bg-status-<%= job.status %>-light">
|
||||||
</span>
|
<%= job.id %>
|
||||||
|
</span>
|
||||||
|
<% end %>
|
||||||
</td>
|
</td>
|
||||||
<td class="p-2 py-3 text-center">
|
<td class="p-2 py-3 text-center">
|
||||||
<% if job.pdf.attached? %>
|
<% if job.pdf.attached? && job.pdf.previewable? %>
|
||||||
<%= link_to_if job.printing?, image_tag(url_for(job.pdf.preview(resize_to_limit: [100, 100])), class:"shadow-lg"), job.pdf, target: "_blank" %>
|
<%= link_to_if job.printing?, image_tag(url_for(job.pdf.preview(resize_to_limit: [100, 100])), class:"shadow-lg"), job.pdf, target: "_blank" %>
|
||||||
<!--<iframe src=<%= url_for(job.pdf) %> width="500" height="700" style="border: none;"></iframe>-->
|
<!--<iframe src=<%= url_for(job.pdf) %> width="500" height="700" style="border: none;"></iframe>-->
|
||||||
<% end %>
|
<% end %>
|
||||||
</td>
|
</td>
|
||||||
<td class="p-2 py-3">
|
<td class="p-2 py-3">
|
||||||
<%= job.costumer_fullname %>
|
<%= job.customer_fullname %>
|
||||||
</td>
|
</td>
|
||||||
<td class="p-2 py-3">
|
<td class="p-2 py-3">
|
||||||
<% if job.pdf.attached? %>
|
<% if job.pdf.attached? %>
|
||||||
<%= link_to_if job.printing?, icon("document-arrow-down", class: "text-hsrm-gray #{ unless job.printing?; 'text-opacity-25' else; 'hover:text-opacity-75'; end} size-6 inline", title: "Download"), job.pdf, download:true %>
|
<% #= link_to job.pdf.filename, rails_blob_path(job.pdf, disposition: "attachment") %>
|
||||||
<%#= link_to job.pdf.filename, rails_blob_path(job.pdf, disposition: "attachment") %>
|
|
||||||
<%= link_to_if job.printing?, truncate(job.pdf.filename.to_s, length: 45), job.pdf, download:true %>
|
<%= link_to_if job.printing?, truncate(job.pdf.filename.to_s, length: 45), job.pdf, download:true %>
|
||||||
<span class="ml-2 badge">
|
<% if job.printing? %>
|
||||||
<%=number_to_human_size job.pdf.blob.byte_size%>
|
<%= link_to job.pdf, download:true do %>
|
||||||
</span>
|
<span class="badge badge-hover">
|
||||||
|
<%= icon("document-arrow-down", class: "text-hsrm-gray size-6 inline", title: "Download") %>
|
||||||
|
<%= number_to_human_size job.pdf.blob.byte_size %>
|
||||||
|
</span>
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
||||||
<% end %>
|
<% end %>
|
||||||
</td>
|
</td>
|
||||||
<% Job::AVAILABLE_PAGE_FORMATS.each do |din| %>
|
<% Job::AVAILABLE_PAGE_FORMATS.each do |din| %>
|
||||||
<td class="p-1 py-3">
|
<td class="p-1 py-3">
|
||||||
<% if job.printing? %>
|
<% if job.printing? %>
|
||||||
<div class="flex flex-col items-center">
|
<div class="flex flex-col items-center">
|
||||||
<span class="badge badge-hover">
|
<span class="p-1 badge badge-hover">
|
||||||
<%= button_to icon("chevron-up", class: "size-5 inline", title: "erhöhen"), increment_page_operator_job_path(job, din:), method: :patch, form_class: "inline" %>
|
<%= button_to icon("plus", class: "size-5 inline", title: "erhöhen"), increment_page_operator_job_path(job, din:), method: :patch, form_class: "inline" %>
|
||||||
</span>
|
</span>
|
||||||
<% end %>
|
<% end %>
|
||||||
<span class="badge">
|
<span class="badge">
|
||||||
<%= job.public_send("number_of_plans_#{din}") if job.respond_to? "number_of_plans_#{din}" %>
|
<%= job.public_send("number_of_plans_#{din}") if job.respond_to? "number_of_plans_#{din}" %>
|
||||||
</span>
|
</span>
|
||||||
<% if job.printing? %>
|
<% if job.printing? %>
|
||||||
<span class="badge badge-hover">
|
<span class="p-1 badge badge-hover">
|
||||||
<%= button_to icon("chevron-down", class: "size-5 inline", title: "verringern"), decrement_page_operator_job_path(job, din:), method: :patch, form_class: "inline" %>
|
<%= button_to icon("minus", class: "size-5 inline", title: "verringern"), decrement_page_operator_job_path(job, din:), method: :patch, form_class: "inline" %>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
</td>
|
</td>
|
||||||
<% end %>
|
<% end %>
|
||||||
<td class="p-2 py-3 text-right">
|
<td class="p-2 py-3 text-right">
|
||||||
<span class="badge">
|
<% if job.printing? %>
|
||||||
<%= job.costum_qm_plan.round(2) %> m²
|
<%= link_to edit_operator_job_path(job) do %>
|
||||||
</span>
|
<span class="badge badge-hover">
|
||||||
|
<%= number_with_delimiter job.costum_qm_plan.round(2) %> m²
|
||||||
|
</span>
|
||||||
|
<% end %>
|
||||||
|
<% else %>
|
||||||
|
<span class="badge">
|
||||||
|
<%= number_with_delimiter job.costum_qm_plan.round(2) %> m²
|
||||||
|
</span>
|
||||||
|
<% end %>
|
||||||
</td>
|
</td>
|
||||||
<td class="w-24 p-2 py-3 text-right">
|
<td class="w-24 p-2 py-3 text-right">
|
||||||
<span class="badge">
|
<span class="badge">
|
||||||
<%= job.cost.round(2) %> €
|
<%= number_to_currency job.cost, locale: :de %>
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
<td class="p-2 py-3">
|
<td class="p-2 py-3">
|
||||||
@@ -60,29 +74,29 @@
|
|||||||
<td class="p-2 py-3 text-right">
|
<td class="p-2 py-3 text-right">
|
||||||
<!-- TODO: move logic to model -->
|
<!-- TODO: move logic to model -->
|
||||||
<% if job.printing? || job.canceled? || job.paid? %>
|
<% if job.printing? || job.canceled? || job.paid? %>
|
||||||
<%= button_to icon(status_icon(:open), class: "icon", title: "Zurück in die Warteschlange"), operator_job_path(job), method: :patch, params: {:job => {status: :open}}, form_class: "inline" %>
|
<%= button_to icon(status_icon(:open), class: "icon icon-hover", title: "Zurück in die Warteschlange"), operator_job_path(job), method: :patch, params: {:job => {status: :open}}, form_class: "inline" %>
|
||||||
<% else %>
|
<% else %>
|
||||||
<%= icon(status_icon(:open), class: "icon icon-disabled", title: "") %>
|
<%= icon(status_icon(:open), class: "icon icon-disabled", title: "") %>
|
||||||
<% end %>
|
<% end %>
|
||||||
<% if job.open? || job.canceled? || job.paid? %>
|
<% if job.open? || job.canceled? || job.paid? %>
|
||||||
<%= button_to icon(status_icon(:printing), class: "icon", title: "Drucken"), operator_job_path(job), method: :patch, params: {:job => {status: :printing}}, form_class: "inline" %>
|
<%= button_to icon(status_icon(:printing), class: "icon icon-hover", title: "Drucken"), operator_job_path(job), method: :patch, params: {:job => {status: :printing}}, form_class: "inline" %>
|
||||||
<% else %>
|
<% else %>
|
||||||
<%= icon(status_icon(:printing), class: "icon icon-disabled", title: "") %>
|
<%= icon(status_icon(:printing), class: "icon icon-disabled", title: "") %>
|
||||||
<% end %>
|
<% end %>
|
||||||
<% if job.printing? || job.paid? %>
|
<% if job.printing? || job.paid? %>
|
||||||
<% job.printing? && turbo_confirm = 'Sind die Pläne gedruckt und die Seitenanzahl und QM korrekt?' %>
|
<% job.printing? && turbo_confirm = 'Sind die Pläne gedruckt und die Seitenanzahl und QM korrekt?' %>
|
||||||
<%= button_to icon(status_icon(:pickup), class: "icon", title: "Pläne sind fertig gedruckt und bereit abgeholt zu werden."), operator_job_path(job), method: :patch, params: {:job => {status: :pickup}}, form: {data: {turbo_confirm: turbo_confirm}}, form_class: "inline" %>
|
<%= button_to icon(status_icon(:pickup), class: "icon icon-hover", title: "Pläne sind fertig gedruckt und bereit abgeholt zu werden."), operator_job_path(job), method: :patch, params: {:job => {status: :pickup}}, form: {data: {turbo_confirm: turbo_confirm}}, form_class: "inline" %>
|
||||||
<% else %>
|
<% else %>
|
||||||
<%= icon(status_icon(:pickup), class: "icon icon-disabled", title: "") %>
|
<%= icon(status_icon(:pickup), class: "icon icon-disabled", title: "") %>
|
||||||
<% end %>
|
<% end %>
|
||||||
<% if job.pickup? || job.printing? %>
|
<% if job.pickup? || job.printing? %>
|
||||||
<% job.printing? && turbo_confirm = 'Sind die Pläne gedruckt und die Seitenanzahl und QM korrekt?' %>
|
<% job.printing? && turbo_confirm = 'Sind die Pläne gedruckt und die Seitenanzahl und QM korrekt?' %>
|
||||||
<%= button_to icon(status_icon(:paid), class: "icon", title: "Bezahlt"), operator_job_path(job), method: :patch, params: {:job => {status: :paid}}, form: {data: {turbo_confirm: turbo_confirm}}, form_class: "inline" %>
|
<%= button_to icon(status_icon(:paid), class: "icon icon-hover", title: "Bezahlt und abgeholt"), operator_job_path(job), method: :patch, params: {:job => {status: :paid}}, form: {data: {turbo_confirm: turbo_confirm}}, form_class: "inline" %>
|
||||||
<% else %>
|
<% else %>
|
||||||
<%= icon(status_icon(:paid), class: "icon icon-disabled ", title: "") %>
|
<%= icon(status_icon(:paid), class: "icon icon-disabled ", title: "") %>
|
||||||
<% end %>
|
<% end %>
|
||||||
<% if job.open? || job.printing? || job.pickup? %>
|
<% if job.open? || job.printing? || job.pickup? %>
|
||||||
<%= button_to icon(status_icon(:canceled), class: "icon text-hsrm-red", title: "Abbrechen"), operator_job_path(job), method: :patch, params: {:job => {status: :canceled}}, form: {data: {turbo_confirm: 'Den Plottauftrag wirklich abbrechen?'}}, form_class: "inline" %>
|
<%= button_to icon(status_icon(:canceled), class: "icon icon-hover text-hsrm-red", title: "Abbrechen"), operator_job_path(job), method: :patch, params: {:job => {status: :canceled}}, form: {data: {turbo_confirm: 'Den Plottauftrag wirklich abbrechen?'}}, form_class: "inline" %>
|
||||||
<% else %>
|
<% else %>
|
||||||
<%= icon(status_icon(:canceled), class: "icon icon-disabled", title: "Kann nicht mehr abgebrochen werden") %>
|
<%= icon(status_icon(:canceled), class: "icon icon-disabled", title: "Kann nicht mehr abgebrochen werden") %>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|||||||
@@ -2,14 +2,14 @@
|
|||||||
<% if jobs.any? %>
|
<% if jobs.any? %>
|
||||||
<%= button_to icon("printer",
|
<%= button_to icon("printer",
|
||||||
class: "icon icon-nohover size-6 mr-2",
|
class: "icon icon-nohover size-6 mr-2",
|
||||||
title: "Drucken") + "Start next job (" + jobs.count.to_s + ")", operator_job_path(jobs.first),
|
title: "Drucken") + "Nächsten Druckauftrag starten (" + jobs.size.to_s + ")", operator_job_path(jobs.first),
|
||||||
params: { :job => { status: :printing} },
|
params: { :job => { status: :printing} },
|
||||||
method: :patch,
|
method: :patch,
|
||||||
form_class: "btn bg-green-400 text-black" %>
|
form_class: "btn bg-green-400 text-black" %>
|
||||||
<% else %>
|
<% else %>
|
||||||
<span class="flex items-center bg-gray-300 bg-opacity-80 btn hover:bg-opacity-80 text-hsrm-gray-light">
|
<span class="flex items-center bg-gray-300 bg-opacity-80 btn hover:bg-opacity-80 text-hsrm-gray-light">
|
||||||
<%= icon("printer", class: "icon icon-nohover size-6 mr-2", title: "") %>
|
<%= icon("printer", class: "icon icon-nohover size-6 mr-2", title: "") %>
|
||||||
Start next job
|
Nächsten Druckauftrag starten
|
||||||
</span>
|
</span>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,8 +1,18 @@
|
|||||||
<div class="mx-auto md:w-2/3 w-full">
|
<div id="<%= dom_id @job %>" class="flex flex-row space-x-4 shadow">
|
||||||
<h1 class="font-bold text-4xl">Editing job</h1>
|
<div>
|
||||||
|
<% if @job.pdf.attached? && @job.pdf.previewable? %>
|
||||||
<%= render "form", job: @job %>
|
<embed
|
||||||
|
type="application/pdf"
|
||||||
<%= link_to "Show this job", @job, class: "ml-2 rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium" %>
|
src="<%= url_for(@job.pdf) %> #view=Fit"
|
||||||
<%= link_to "Back to jobs", jobs_path, class: "ml-2 rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium" %>
|
width="700px"
|
||||||
|
height="900px"
|
||||||
|
class=""
|
||||||
|
/>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<%= render "form", job: @job %>
|
||||||
|
<%= link_to "Show this job", operator_job_path(@job), class: "btn" %>
|
||||||
|
<%= link_to "Back to jobs", operator_jobs_path, class: "btn" %>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -15,7 +15,12 @@
|
|||||||
<%= icon(status_icon(:printing), class: "icon") %>
|
<%= icon(status_icon(:printing), class: "icon") %>
|
||||||
Printing
|
Printing
|
||||||
</h1>
|
</h1>
|
||||||
<%= render partial: 'start_next_job_btn', locals: { jobs: @openjobs } %>
|
<div class="flex gap-2">
|
||||||
|
<div id="start_manual_job_btn">
|
||||||
|
<%= link_to icon("plus-circle", class: "icon icon-nohover size-6 mr-2", title: "Druckauftrag erstellen") + "Druckauftrag erstellen" , new_operator_job_path, class: "btn block bg-green-400 text-black" %>
|
||||||
|
</div>
|
||||||
|
<%= render partial: 'start_next_job_btn', locals: { jobs: @openjobs } %>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<%# render partial: "job_card", collection: @printingjobs, as: :job %>
|
<%# render partial: "job_card", collection: @printingjobs, as: :job %>
|
||||||
<div class="min-w-full overflow-auto shadow-lg">
|
<div class="min-w-full overflow-auto shadow-lg">
|
||||||
|
|||||||
5
app/views/operator/jobs/new.html.erb
Normal file
5
app/views/operator/jobs/new.html.erb
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<div class="mx-auto md:w-2/3 w-full">
|
||||||
|
<h1 class="font-bold text-4xl">Druckauftrag erstellen</h1>
|
||||||
|
<%= render "form", job: @job %>
|
||||||
|
<%= link_to "Zurück zur Übersicht", operator_jobs_path, class: "ml-2 rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium" %>
|
||||||
|
</div>
|
||||||
@@ -1,15 +1,8 @@
|
|||||||
<div class="mx-auto md:w-2/3 w-full flex">
|
<div class="container flex w-full mx-auto">
|
||||||
<div class="mx-auto">
|
<div class="mx-auto">
|
||||||
<% if notice.present? %>
|
<% if notice.present? %>
|
||||||
<p class="py-2 px-3 bg-green-50 mb-5 text-green-500 font-medium rounded-lg inline-block" id="notice"><%= notice %></p>
|
<p class="inline-block px-3 py-2 mb-5 font-medium text-green-500 rounded-lg bg-green-50" id="notice"><%= notice %></p>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<%= render @job %>
|
<%= render @job %>
|
||||||
|
|
||||||
<%= link_to "Edit this job", edit_job_path(@job), class: "mt-2 rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium" %>
|
|
||||||
<%= link_to "Back to jobs", jobs_path, class: "ml-2 rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium" %>
|
|
||||||
<div class="inline-block ml-2">
|
|
||||||
<%= button_to "Destroy this job", @job, method: :delete, class: "mt-2 rounded-lg py-3 px-5 bg-gray-100 font-medium" %>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
4
app/views/profiles/destroy.html.erb
Normal file
4
app/views/profiles/destroy.html.erb
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<div>
|
||||||
|
<h1 class="font-bold text-4xl">Profiles#destroy</h1>
|
||||||
|
<p>Find me in app/views/profiles/destroy.html.erb</p>
|
||||||
|
</div>
|
||||||
4
app/views/profiles/edit.html.erb
Normal file
4
app/views/profiles/edit.html.erb
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<div>
|
||||||
|
<h1 class="font-bold text-4xl">Profiles#edit</h1>
|
||||||
|
<p>Find me in app/views/profiles/edit.html.erb</p>
|
||||||
|
</div>
|
||||||
74
app/views/profiles/show.html.erb
Normal file
74
app/views/profiles/show.html.erb
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
<div>
|
||||||
|
<h1 class="p-1 text-4xl font-bold border-b-2 border-hsrm-red">Profile</h1>
|
||||||
|
<ul>
|
||||||
|
<li>Name: <%= current_user.name %>
|
||||||
|
<% if is_admin_or_operator? %>
|
||||||
|
<p class="inline badge"><%= current_user.role %></p>
|
||||||
|
<% end %>
|
||||||
|
</li>
|
||||||
|
<li>E-Mail: <%= current_user.email %></li>
|
||||||
|
<% if current_user.verified? %>
|
||||||
|
<p>
|
||||||
|
E-Mail is verified
|
||||||
|
</p>
|
||||||
|
<% else %>
|
||||||
|
<p>
|
||||||
|
<div>
|
||||||
|
Please validate your E-mail-adress (<%= button_to 'Re-send verification email', identity_email_verification_path, form_class: "inline" %>)
|
||||||
|
</div>
|
||||||
|
</p>
|
||||||
|
<% end %>
|
||||||
|
</ul>
|
||||||
|
<h2 class="p-1 text-lg font-bold border-b-2 border-hsrm-red">Aufgegebene Druckaufträge</h2>
|
||||||
|
<p>
|
||||||
|
Aufgegebene Druckaufträge
|
||||||
|
<%= current_user.customer_jobs.size %>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Abgebrochene Druckaufgräge
|
||||||
|
<%= current_user.customer_jobs.canceled.size %>
|
||||||
|
</p>
|
||||||
|
<% if is_admin_or_operator? %>
|
||||||
|
<h2 class="p-1 text-lg font-bold border-b-2 border-hsrm-red">Bearbeitete Druckaufträge</h2>
|
||||||
|
<p>
|
||||||
|
Gedruckte Druckaufträge
|
||||||
|
<%= current_user.operator_jobs.paid.size %>
|
||||||
|
</p>
|
||||||
|
<% end %>
|
||||||
|
<h2 class="p-1 text-lg font-bold border-b-2 border-hsrm-red">Actions</h2>
|
||||||
|
<div>
|
||||||
|
<%= link_to "Change password", edit_password_path %>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<%= link_to "Change email address", edit_identity_email_path %>
|
||||||
|
</div>
|
||||||
|
<h2 class="p-1 text-lg font-bold border-b-2 border-hsrm-red">Access history</h2>
|
||||||
|
<div>
|
||||||
|
<%= link_to "Devices & Sessions", sessions_path %>
|
||||||
|
</div>
|
||||||
|
<br>
|
||||||
|
<%= button_to "Log out", Current.session, method: :delete, class: "btn btn-primary" %>
|
||||||
|
</div>
|
||||||
|
<h1 class="py-4 text-4xl font-bold text-hsrm-gray">Die letzten 10 Druckaufträge</h1>
|
||||||
|
<div class="min-w-full overflow-auto shadow-lg">
|
||||||
|
<table class="w-full py-8 table-auto">
|
||||||
|
<thead class="font-semibold tracking-wide bg-gray-200 border-b-2 border-gray-300 text text-hsrm-gray">
|
||||||
|
<tr>
|
||||||
|
<th class="w-1 p-2 py-3 text-center"> ID </th>
|
||||||
|
<th class="w-1 p-2 py-3 text-center"> Vorschau </th>
|
||||||
|
<th class="w-1 p-2 py-3 text-left"> Auftraggeber </th>
|
||||||
|
<th class="p-2 py-3 text-left"> PDF </th>
|
||||||
|
<th class="w-1 p-1 py-3 text-left"> A0 </th>
|
||||||
|
<th class="w-1 p-1 py-3 text-left"> A1 </th>
|
||||||
|
<th class="w-1 p-1 py-3 text-left"> A2 </th>
|
||||||
|
<th class="w-1 p-1 py-3 text-left"> A3 </th>
|
||||||
|
<th class="w-1 p-2 py-3 text-center text-nowrap"> no DIN </th>
|
||||||
|
<th class="w-1 p-2 py-3 text-center"> Kosten </th>
|
||||||
|
<th class="w-1 p-2 py-3 text-center"> Status </th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody id='jobs' class="divide-y divivde-gray-300">
|
||||||
|
<%= render partial: "jobs/job_tr", collection: current_user.customer_jobs.order(created_at: :desc).limit(10), as: :job, locals: { no_actions: true } %>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
@@ -1,10 +1,8 @@
|
|||||||
<h1>Sign up</h1>
|
<h1>Sign up</h1>
|
||||||
|
|
||||||
<%= form_with(url: sign_up_path) do |form| %>
|
<%= form_with(url: sign_up_path) do |form| %>
|
||||||
<% if @user.errors.any? %>
|
<% if @user.errors.any? %>
|
||||||
<div style="color: red">
|
<div style="color: red">
|
||||||
<h2><%= pluralize(@user.errors.count, "error") %> prohibited this user from being saved:</h2>
|
<h2><%= pluralize(@user.errors.count, "error") %> prohibited this user from being saved:</h2>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<% @user.errors.each do |error| %>
|
<% @user.errors.each do |error| %>
|
||||||
<li><%= error.full_message %></li>
|
<li><%= error.full_message %></li>
|
||||||
@@ -12,23 +10,27 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
<div>
|
||||||
|
<%= form.label :firstname, style: "display: block" %>
|
||||||
|
<%= form.text_field :firstname, value: @user.firstname, required: true, autofocus: true %>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<%= form.label :lastname, style: "display: block" %>
|
||||||
|
<%= form.text_field :lastname, value: @user.lastname, required: true %>
|
||||||
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<%= form.label :email, style: "display: block" %>
|
<%= form.label :email, style: "display: block" %>
|
||||||
<%= form.email_field :email, value: @user.email, required: true, autofocus: true, autocomplete: "email" %>
|
<%= form.email_field :email, value: @user.email, required: true, autocomplete: "email" %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<%= form.label :password, style: "display: block" %>
|
<%= form.label :password, style: "display: block" %>
|
||||||
<%= form.password_field :password, required: true, autocomplete: "new-password" %>
|
<%= form.password_field :password, required: true, autocomplete: "new-password" %>
|
||||||
<div>12 characters minimum.</div>
|
<div>12 characters minimum.</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<%= form.label :password_confirmation, style: "display: block" %>
|
<%= form.label :password_confirmation, style: "display: block" %>
|
||||||
<%= form.password_field :password_confirmation, required: true, autocomplete: "new-password" %>
|
<%= form.password_field :password_confirmation, required: true, autocomplete: "new-password" %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<%= form.submit "Sign up" %>
|
<%= form.submit "Sign up" %>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ module Plottservice
|
|||||||
# config.time_zone = "Central Time (US & Canada)"
|
# config.time_zone = "Central Time (US & Canada)"
|
||||||
# config.eager_load_paths << Rails.root.join("extras")
|
# config.eager_load_paths << Rails.root.join("extras")
|
||||||
|
|
||||||
# config.i18n.default_locale = :de
|
config.i18n.available_locales = [ :en, :de ]
|
||||||
|
config.i18n.default_locale = :de
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
5
config/initializers/active_storage.rb
Normal file
5
config/initializers/active_storage.rb
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
ActiveSupport.on_load(:active_storage_blob) do
|
||||||
|
def self.ransackable_attributes(auth_object = nil)
|
||||||
|
%w[filename]
|
||||||
|
end
|
||||||
|
end
|
||||||
220
config/initializers/pagy.rb
Normal file
220
config/initializers/pagy.rb
Normal file
@@ -0,0 +1,220 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
# Pagy initializer file (9.0.9)
|
||||||
|
# Customize only what you really need and notice that the core Pagy works also without any of the following lines.
|
||||||
|
# Should you just cherry pick part of this file, please maintain the require-order of the extras
|
||||||
|
|
||||||
|
|
||||||
|
# Pagy Variables
|
||||||
|
# See https://ddnexus.github.io/pagy/docs/api/pagy#variables
|
||||||
|
# You can set any pagy variable as a Pagy::DEFAULT. They can also be overridden per instance by just passing them to
|
||||||
|
# Pagy.new|Pagy::Countless.new|Pagy::Calendar::*.new or any of the #pagy* controller methods
|
||||||
|
# Here are the few that make more sense as DEFAULTs:
|
||||||
|
# Pagy::DEFAULT[:limit] = 20 # default
|
||||||
|
# Pagy::DEFAULT[:size] = 7 # default
|
||||||
|
# Pagy::DEFAULT[:ends] = true # default
|
||||||
|
# Pagy::DEFAULT[:page_param] = :page # default
|
||||||
|
# Pagy::DEFAULT[:count_args] = [] # example for non AR ORMs
|
||||||
|
# Pagy::DEFAULT[:max_pages] = 3000 # example
|
||||||
|
|
||||||
|
|
||||||
|
# Extras
|
||||||
|
# See https://ddnexus.github.io/pagy/categories/extra
|
||||||
|
|
||||||
|
|
||||||
|
# Legacy Compatibility Extras
|
||||||
|
|
||||||
|
# Size extra: Enable the Array type for the `:size` variable (e.g. `size: [1,4,4,1]`)
|
||||||
|
# See https://ddnexus.github.io/pagy/docs/extras/size
|
||||||
|
# require 'pagy/extras/size' # must be required before the other extras
|
||||||
|
|
||||||
|
|
||||||
|
# Backend Extras
|
||||||
|
|
||||||
|
# Arel extra: For better performance utilizing grouped ActiveRecord collections:
|
||||||
|
# See: https://ddnexus.github.io/pagy/docs/extras/arel
|
||||||
|
# require 'pagy/extras/arel'
|
||||||
|
|
||||||
|
# Array extra: Paginate arrays efficiently, avoiding expensive array-wrapping and without overriding
|
||||||
|
# See https://ddnexus.github.io/pagy/docs/extras/array
|
||||||
|
# require 'pagy/extras/array'
|
||||||
|
|
||||||
|
# Calendar extra: Add pagination filtering by calendar time unit (year, quarter, month, week, day)
|
||||||
|
# See https://ddnexus.github.io/pagy/docs/extras/calendar
|
||||||
|
require "pagy/extras/calendar"
|
||||||
|
# Default for each calendar unit class in IRB:
|
||||||
|
# >> Pagy::Calendar::Year::DEFAULT
|
||||||
|
# >> Pagy::Calendar::Quarter::DEFAULT
|
||||||
|
# >> Pagy::Calendar::Month::DEFAULT
|
||||||
|
# >> Pagy::Calendar::Week::DEFAULT
|
||||||
|
# >> Pagy::Calendar::Day::DEFAULT
|
||||||
|
#
|
||||||
|
# Uncomment the following lines, if you need calendar localization without using the I18n extra
|
||||||
|
# module LocalizePagyCalendar
|
||||||
|
# def localize(time, opts)
|
||||||
|
# ::I18n.l(time, **opts)
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
# Pagy::Calendar.prepend LocalizePagyCalendar
|
||||||
|
|
||||||
|
# Countless extra: Paginate without any count, saving one query per rendering
|
||||||
|
# See https://ddnexus.github.io/pagy/docs/extras/countless
|
||||||
|
# require 'pagy/extras/countless'
|
||||||
|
# Pagy::DEFAULT[:countless_minimal] = false # default (eager loading)
|
||||||
|
|
||||||
|
# Elasticsearch Rails extra: Paginate `ElasticsearchRails::Results` objects
|
||||||
|
# See https://ddnexus.github.io/pagy/docs/extras/elasticsearch_rails
|
||||||
|
# Default :pagy_search method: change only if you use also
|
||||||
|
# the searchkick or meilisearch extra that defines the same
|
||||||
|
# Pagy::DEFAULT[:elasticsearch_rails_pagy_search] = :pagy_search
|
||||||
|
# Default original :search method called internally to do the actual search
|
||||||
|
# Pagy::DEFAULT[:elasticsearch_rails_search] = :search
|
||||||
|
# require 'pagy/extras/elasticsearch_rails'
|
||||||
|
|
||||||
|
# Headers extra: http response headers (and other helpers) useful for API pagination
|
||||||
|
# See https://ddnexus.github.io/pagy/docs/extras/headers
|
||||||
|
# require 'pagy/extras/headers'
|
||||||
|
# Pagy::DEFAULT[:headers] = { page: 'Current-Page',
|
||||||
|
# limit: 'Page-Items',
|
||||||
|
# count: 'Total-Count',
|
||||||
|
# pages: 'Total-Pages' } # default
|
||||||
|
|
||||||
|
# Keyset extra: Paginate with the Pagy keyset pagination technique
|
||||||
|
# See https://ddnexus.github.io/pagy/docs/extras/keyset
|
||||||
|
# require 'pagy/extras/keyset'
|
||||||
|
|
||||||
|
# Meilisearch extra: Paginate `Meilisearch` result objects
|
||||||
|
# See https://ddnexus.github.io/pagy/docs/extras/meilisearch
|
||||||
|
# Default :pagy_search method: change only if you use also
|
||||||
|
# the elasticsearch_rails or searchkick extra that define the same method
|
||||||
|
# Pagy::DEFAULT[:meilisearch_pagy_search] = :pagy_search
|
||||||
|
# Default original :search method called internally to do the actual search
|
||||||
|
# Pagy::DEFAULT[:meilisearch_search] = :ms_search
|
||||||
|
# require 'pagy/extras/meilisearch'
|
||||||
|
|
||||||
|
# Metadata extra: Provides the pagination metadata to Javascript frameworks like Vue.js, react.js, etc.
|
||||||
|
# See https://ddnexus.github.io/pagy/docs/extras/metadata
|
||||||
|
# you must require the JS Tools internal extra (BEFORE the metadata extra) ONLY if you need also the :sequels
|
||||||
|
# require 'pagy/extras/js_tools'
|
||||||
|
# require 'pagy/extras/metadata'
|
||||||
|
# For performance reasons, you should explicitly set ONLY the metadata you use in the frontend
|
||||||
|
# Pagy::DEFAULT[:metadata] = %i[scaffold_url page prev next last] # example
|
||||||
|
|
||||||
|
# Searchkick extra: Paginate `Searchkick::Results` objects
|
||||||
|
# See https://ddnexus.github.io/pagy/docs/extras/searchkick
|
||||||
|
# Default :pagy_search method: change only if you use also
|
||||||
|
# the elasticsearch_rails or meilisearch extra that defines the same
|
||||||
|
# Pagy::DEFAULT[:searchkick_pagy_search] = :pagy_search
|
||||||
|
# Default original :search method called internally to do the actual search
|
||||||
|
# Pagy::DEFAULT[:searchkick_search] = :search
|
||||||
|
# require 'pagy/extras/searchkick'
|
||||||
|
# uncomment if you are going to use Searchkick.pagy_search
|
||||||
|
# Searchkick.extend Pagy::Searchkick
|
||||||
|
|
||||||
|
|
||||||
|
# Frontend Extras
|
||||||
|
|
||||||
|
# Bootstrap extra: Add nav, nav_js and combo_nav_js helpers and templates for Bootstrap pagination
|
||||||
|
# See https://ddnexus.github.io/pagy/docs/extras/bootstrap
|
||||||
|
# require 'pagy/extras/bootstrap'
|
||||||
|
|
||||||
|
# Bulma extra: Add nav, nav_js and combo_nav_js helpers and templates for Bulma pagination
|
||||||
|
# See https://ddnexus.github.io/pagy/docs/extras/bulma
|
||||||
|
# require 'pagy/extras/bulma'
|
||||||
|
|
||||||
|
# Pagy extra: Add the pagy styled versions of the javascript-powered navs
|
||||||
|
# and a few other components to the Pagy::Frontend module.
|
||||||
|
# See https://ddnexus.github.io/pagy/docs/extras/pagy
|
||||||
|
# require 'pagy/extras/pagy'
|
||||||
|
|
||||||
|
# Multi size var used by the *_nav_js helpers
|
||||||
|
# See https://ddnexus.github.io/pagy/docs/extras/pagy#steps
|
||||||
|
# Pagy::DEFAULT[:steps] = { 0 => 5, 540 => 7, 720 => 9 } # example
|
||||||
|
|
||||||
|
|
||||||
|
# Feature Extras
|
||||||
|
|
||||||
|
# Gearbox extra: Automatically change the limit per page depending on the page number
|
||||||
|
# See https://ddnexus.github.io/pagy/docs/extras/gearbox
|
||||||
|
# require 'pagy/extras/gearbox'
|
||||||
|
# set to false only if you want to make :gearbox_extra an opt-in variable
|
||||||
|
# Pagy::DEFAULT[:gearbox_extra] = false # default true
|
||||||
|
# Pagy::DEFAULT[:gearbox_limit] = [15, 30, 60, 100] # default
|
||||||
|
|
||||||
|
# Limit extra: Allow the client to request a custom limit per page with an optional selector UI
|
||||||
|
# See https://ddnexus.github.io/pagy/docs/extras/limit
|
||||||
|
# require 'pagy/extras/limit'
|
||||||
|
# set to false only if you want to make :limit_extra an opt-in variable
|
||||||
|
# Pagy::DEFAULT[:limit_extra] = false # default true
|
||||||
|
# Pagy::DEFAULT[:limit_param] = :limit # default
|
||||||
|
# Pagy::DEFAULT[:limit_max] = 100 # default
|
||||||
|
|
||||||
|
# Overflow extra: Allow for easy handling of overflowing pages
|
||||||
|
# See https://ddnexus.github.io/pagy/docs/extras/overflow
|
||||||
|
# require 'pagy/extras/overflow'
|
||||||
|
# Pagy::DEFAULT[:overflow] = :empty_page # default (other options: :last_page and :exception)
|
||||||
|
|
||||||
|
# Trim extra: Remove the page=1 param from links
|
||||||
|
# See https://ddnexus.github.io/pagy/docs/extras/trim
|
||||||
|
require "pagy/extras/trim"
|
||||||
|
# set to false only if you want to make :trim_extra an opt-in variable
|
||||||
|
# Pagy::DEFAULT[:trim_extra] = false # default true
|
||||||
|
|
||||||
|
# Standalone extra: Use pagy in non Rack environment/gem
|
||||||
|
# See https://ddnexus.github.io/pagy/docs/extras/standalone
|
||||||
|
# require 'pagy/extras/standalone'
|
||||||
|
# Pagy::DEFAULT[:url] = 'http://www.example.com/subdir' # optional default
|
||||||
|
|
||||||
|
# Jsonapi extra: Implements JSON:API specifications
|
||||||
|
# See https://ddnexus.github.io/pagy/docs/extras/jsonapi
|
||||||
|
# require 'pagy/extras/jsonapi' # must be required after the other extras
|
||||||
|
# set to false only if you want to make :jsonapi an opt-in variable
|
||||||
|
# Pagy::DEFAULT[:jsonapi] = false # default true
|
||||||
|
|
||||||
|
# Rails
|
||||||
|
# Enable the .js file required by the helpers that use javascript
|
||||||
|
# (pagy*_nav_js, pagy*_combo_nav_js, and pagy_limit_selector_js)
|
||||||
|
# See https://ddnexus.github.io/pagy/docs/api/javascript
|
||||||
|
|
||||||
|
# With the asset pipeline
|
||||||
|
# Sprockets need to look into the pagy javascripts dir, so add it to the assets paths
|
||||||
|
# Rails.application.config.assets.paths << Pagy.root.join('javascripts')
|
||||||
|
|
||||||
|
# I18n
|
||||||
|
|
||||||
|
# Pagy internal I18n: ~18x faster using ~10x less memory than the i18n gem
|
||||||
|
# See https://ddnexus.github.io/pagy/docs/api/i18n
|
||||||
|
# Notice: No need to configure anything in this section if your app uses only "en"
|
||||||
|
# or if you use the i18n extra below
|
||||||
|
#
|
||||||
|
# Examples:
|
||||||
|
# load the "de" built-in locale:
|
||||||
|
# Pagy::I18n.load(locale: 'de')
|
||||||
|
#
|
||||||
|
# load the "de" locale defined in the custom file at :filepath:
|
||||||
|
# Pagy::I18n.load(locale: 'de', filepath: 'path/to/pagy-de.yml')
|
||||||
|
#
|
||||||
|
# load the "de", "en" and "es" built-in locales:
|
||||||
|
# (the first passed :locale will be used also as the default_locale)
|
||||||
|
# Pagy::I18n.load({ locale: 'de' },
|
||||||
|
# { locale: 'en' },
|
||||||
|
# { locale: 'es' })
|
||||||
|
#
|
||||||
|
# load the "en" built-in locale, a custom "es" locale,
|
||||||
|
# and a totally custom locale complete with a custom :pluralize proc:
|
||||||
|
# (the first passed :locale will be used also as the default_locale)
|
||||||
|
# Pagy::I18n.load({ locale: 'en' },
|
||||||
|
# { locale: 'es', filepath: 'path/to/pagy-es.yml' },
|
||||||
|
# { locale: 'xyz', # not built-in
|
||||||
|
# filepath: 'path/to/pagy-xyz.yml',
|
||||||
|
# pluralize: lambda{ |count| ... } )
|
||||||
|
|
||||||
|
|
||||||
|
# I18n extra: uses the standard i18n gem which is ~18x slower using ~10x more memory
|
||||||
|
# than the default pagy internal i18n (see above)
|
||||||
|
# See https://ddnexus.github.io/pagy/docs/extras/i18n
|
||||||
|
# require 'pagy/extras/i18n'
|
||||||
|
|
||||||
|
|
||||||
|
# When you are done setting your own default freeze it, so it will not get changed accidentally
|
||||||
|
Pagy::DEFAULT.freeze
|
||||||
22
config/initializers/ransack.rb
Normal file
22
config/initializers/ransack.rb
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
# search date from to including both dates
|
||||||
|
Ransack.configure do |config|
|
||||||
|
config.add_predicate "dategteq",
|
||||||
|
arel_predicate: "gteq",
|
||||||
|
formatter: proc { |v| v.beginning_of_day },
|
||||||
|
type: :date
|
||||||
|
|
||||||
|
config.add_predicate "datelteq",
|
||||||
|
arel_predicate: "lteq",
|
||||||
|
formatter: proc { |v| v.end_of_day },
|
||||||
|
type: :date
|
||||||
|
|
||||||
|
config.custom_arrows = {
|
||||||
|
up_arrow: '<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" role="img" aria-labelledby="ajg9won5sfrpesugbew2i5rtummy29a1" class="icon size-4 inline"><title id="ajg9won5sfrpesugbew2i5rtummy29a1">Bars arrow up</title>
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" d="M3 4.5h14.25M3 9h9.75M3 13.5h5.25m5.25-.75L17.25 9m0 0L21 12.75M17.25 9v12"></path>
|
||||||
|
</svg>',
|
||||||
|
down_arrow: '<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" role="img" aria-labelledby="ar7s290igtz4ebl4u28nvo83f8i49xn3" class="icon size-4"><title id="ar7s290igtz4ebl4u28nvo83f8i49xn3">Bars arrow down</title>
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" d="M3 4.5h14.25M3 9h9.75M3 13.5h9.75m4.5-4.5v12m0 0l-3.75-3.75M17.25 21L21 17.25"></path>
|
||||||
|
</svg>',
|
||||||
|
default_arrow: ""
|
||||||
|
}
|
||||||
|
end
|
||||||
@@ -31,10 +31,15 @@ de:
|
|||||||
activerecord:
|
activerecord:
|
||||||
attributes:
|
attributes:
|
||||||
job:
|
job:
|
||||||
pdf: "PDF Dokument"
|
pdf: "Plan (PDF Format)"
|
||||||
|
privacy_policy: "Datenschutzerklärung"
|
||||||
|
customer_firstname: "Vorname"
|
||||||
|
customer_lastname: "Nachname"
|
||||||
errors:
|
errors:
|
||||||
models:
|
models:
|
||||||
job:
|
job:
|
||||||
attributes:
|
attributes:
|
||||||
pdf:
|
pdf:
|
||||||
blank: "is erforderlich"
|
blank: "is erforderlich"
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -10,15 +10,18 @@ Rails.application.routes.draw do
|
|||||||
resource :email_verification, only: [ :show, :create ]
|
resource :email_verification, only: [ :show, :create ]
|
||||||
resource :password_reset, only: [ :new, :edit, :create, :update ]
|
resource :password_reset, only: [ :new, :edit, :create, :update ]
|
||||||
end
|
end
|
||||||
resources :jobs do
|
resources :jobs, only: [ :index, :new, :create ] do
|
||||||
member do
|
member do
|
||||||
patch "cancel"
|
patch "cancel"
|
||||||
|
get "cancel_button"
|
||||||
|
get "badge"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
resource :profile, only: [ :show, :edit, :destroy ]
|
||||||
namespace :admin do
|
namespace :admin do
|
||||||
resource :users
|
resources :users, only: [ :index, :show, :update ]
|
||||||
resource :jobs
|
resources :jobs, only: [ :index ]
|
||||||
resource :dashboard
|
resource :dashboard, only: [ :show ]
|
||||||
end
|
end
|
||||||
namespace :operator do
|
namespace :operator do
|
||||||
resources :jobs do
|
resources :jobs do
|
||||||
@@ -28,6 +31,7 @@ Rails.application.routes.draw do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
get "home", to: "home#index"
|
||||||
# Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html
|
# Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html
|
||||||
|
|
||||||
# Reveal health status on /up that returns 200 if the app boots with no exceptions, otherwise 500.
|
# Reveal health status on /up that returns 200 if the app boots with no exceptions, otherwise 500.
|
||||||
|
|||||||
@@ -29,6 +29,12 @@ module.exports = {
|
|||||||
"status-paid-light": "#86efac", // green-300
|
"status-paid-light": "#86efac", // green-300
|
||||||
"status-canceled": "#7f1d1d", // red-900
|
"status-canceled": "#7f1d1d", // red-900
|
||||||
"status-canceled-light": "#fca5a5", // red-300
|
"status-canceled-light": "#fca5a5", // red-300
|
||||||
|
"role-user": "#14532d", // green
|
||||||
|
"role-user-light": "#86efac",
|
||||||
|
"role-operator": "#713f12", // yellow
|
||||||
|
"role-operator-light": "#fde047",
|
||||||
|
"role-admin": "#7f1d1d", // red
|
||||||
|
"role-admin-light": "#fca5a5",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -48,6 +54,15 @@ module.exports = {
|
|||||||
"text-status-canceled",
|
"text-status-canceled",
|
||||||
"bg-status-canceled-light",
|
"bg-status-canceled-light",
|
||||||
"border-status-canceled-light",
|
"border-status-canceled-light",
|
||||||
|
"text-role-user",
|
||||||
|
"bg-role-user-light",
|
||||||
|
"text-role-operator",
|
||||||
|
"bg-role-operator-light",
|
||||||
|
"text-role-admin",
|
||||||
|
"bg-role-admin-light",
|
||||||
|
"hover:bg-role-user-light",
|
||||||
|
"hover:bg-role-operator-light",
|
||||||
|
"hover:bg-role-admin-light"
|
||||||
],
|
],
|
||||||
plugins: [
|
plugins: [
|
||||||
require("@tailwindcss/forms"),
|
require("@tailwindcss/forms"),
|
||||||
|
|||||||
@@ -1,20 +1,22 @@
|
|||||||
class CreateJobs < ActiveRecord::Migration[7.1]
|
class CreateJobs < ActiveRecord::Migration[7.1]
|
||||||
def change
|
def change
|
||||||
create_table :jobs do |t|
|
create_table :jobs do |t|
|
||||||
|
t.references :customer, null: true
|
||||||
|
t.references :creator, null: true
|
||||||
|
t.references :cashier, null: true
|
||||||
t.references :operator, null: true
|
t.references :operator, null: true
|
||||||
t.references :costumer, null: true
|
t.string :customer_firstname
|
||||||
|
t.string :customer_lastname
|
||||||
t.string :operator_firstname
|
t.string :operator_firstname
|
||||||
t.string :operator_lastname
|
t.string :operator_lastname
|
||||||
t.string :costumer_firstname
|
t.string :cashier_firstname
|
||||||
t.string :costumer_lastname
|
t.string :cashier_lastname
|
||||||
t.boolean :printed, default: false
|
|
||||||
t.boolean :paid, default: false
|
|
||||||
t.datetime :printed_at
|
t.datetime :printed_at
|
||||||
t.datetime :status_changed_at
|
|
||||||
t.datetime :paid_at
|
t.datetime :paid_at
|
||||||
|
t.datetime :status_changed_at
|
||||||
t.boolean :intern, default: false
|
t.boolean :intern, default: false
|
||||||
t.string :cost_center
|
t.string :cost_center
|
||||||
t.integer :status, default: 0, index: true
|
t.string :status, default: "open", index: true
|
||||||
t.integer :number_of_plans_a0, default: 0
|
t.integer :number_of_plans_a0, default: 0
|
||||||
t.integer :number_of_plans_a1, default: 0
|
t.integer :number_of_plans_a1, default: 0
|
||||||
t.integer :number_of_plans_a2, default: 0
|
t.integer :number_of_plans_a2, default: 0
|
||||||
@@ -22,9 +24,10 @@ class CreateJobs < ActiveRecord::Migration[7.1]
|
|||||||
t.float :costum_qm_plan, default: 0
|
t.float :costum_qm_plan, default: 0
|
||||||
t.float :cost, default: 0
|
t.float :cost, default: 0
|
||||||
t.float :cost_qm, default: 0
|
t.float :cost_qm, default: 0
|
||||||
t.boolean :privacy_policy_accepted, default: false
|
t.boolean :privacy_policy, default: false
|
||||||
|
t.boolean :created_by_operator, default: false
|
||||||
|
|
||||||
t.timestamps
|
t.timestamps
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -6,13 +6,20 @@ class CreateUsers < ActiveRecord::Migration[7.2]
|
|||||||
t.string :firstname
|
t.string :firstname
|
||||||
t.string :lastname
|
t.string :lastname
|
||||||
|
|
||||||
t.integer :role, default: 0, index: true
|
t.string :role, default: "user", index: true
|
||||||
|
|
||||||
t.boolean :verified, null: false, default: false
|
t.boolean :verified, null: false, default: false
|
||||||
|
|
||||||
|
t.integer :customer_jobs_count, default: 0
|
||||||
|
t.integer :operator_jobs_count, default: 0
|
||||||
|
t.integer :created_jobs_count, default: 0
|
||||||
|
t.integer :cashed_jobs_count, default: 0
|
||||||
|
|
||||||
t.timestamps
|
t.timestamps
|
||||||
end
|
end
|
||||||
|
add_foreign_key :jobs, :users, column: :customer_id
|
||||||
add_foreign_key :jobs, :users, column: :operator_id
|
add_foreign_key :jobs, :users, column: :operator_id
|
||||||
add_foreign_key :jobs, :users, column: :costumer_id
|
add_foreign_key :jobs, :users, column: :creator_id
|
||||||
|
add_foreign_key :jobs, :users, column: :cashier_id
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
35
db/schema.rb
generated
35
db/schema.rb
generated
@@ -10,7 +10,7 @@
|
|||||||
#
|
#
|
||||||
# It's strongly recommended that you check this file into your version control system.
|
# It's strongly recommended that you check this file into your version control system.
|
||||||
|
|
||||||
ActiveRecord::Schema[7.2].define(version: 2024_08_26_144016) do
|
ActiveRecord::Schema[8.0].define(version: 2024_08_26_144016) do
|
||||||
create_table "active_storage_attachments", force: :cascade do |t|
|
create_table "active_storage_attachments", force: :cascade do |t|
|
||||||
t.string "name", null: false
|
t.string "name", null: false
|
||||||
t.string "record_type", null: false
|
t.string "record_type", null: false
|
||||||
@@ -40,20 +40,22 @@ ActiveRecord::Schema[7.2].define(version: 2024_08_26_144016) do
|
|||||||
end
|
end
|
||||||
|
|
||||||
create_table "jobs", force: :cascade do |t|
|
create_table "jobs", force: :cascade do |t|
|
||||||
|
t.integer "customer_id"
|
||||||
|
t.integer "creator_id"
|
||||||
|
t.integer "cashier_id"
|
||||||
t.integer "operator_id"
|
t.integer "operator_id"
|
||||||
t.integer "costumer_id"
|
t.string "customer_firstname"
|
||||||
|
t.string "customer_lastname"
|
||||||
t.string "operator_firstname"
|
t.string "operator_firstname"
|
||||||
t.string "operator_lastname"
|
t.string "operator_lastname"
|
||||||
t.string "costumer_firstname"
|
t.string "cashier_firstname"
|
||||||
t.string "costumer_lastname"
|
t.string "cashier_lastname"
|
||||||
t.boolean "printed", default: false
|
|
||||||
t.boolean "paid", default: false
|
|
||||||
t.datetime "printed_at"
|
t.datetime "printed_at"
|
||||||
t.datetime "status_changed_at"
|
|
||||||
t.datetime "paid_at"
|
t.datetime "paid_at"
|
||||||
|
t.datetime "status_changed_at"
|
||||||
t.boolean "intern", default: false
|
t.boolean "intern", default: false
|
||||||
t.string "cost_center"
|
t.string "cost_center"
|
||||||
t.integer "status", default: 0
|
t.string "status", default: "open"
|
||||||
t.integer "number_of_plans_a0", default: 0
|
t.integer "number_of_plans_a0", default: 0
|
||||||
t.integer "number_of_plans_a1", default: 0
|
t.integer "number_of_plans_a1", default: 0
|
||||||
t.integer "number_of_plans_a2", default: 0
|
t.integer "number_of_plans_a2", default: 0
|
||||||
@@ -61,10 +63,13 @@ ActiveRecord::Schema[7.2].define(version: 2024_08_26_144016) do
|
|||||||
t.float "costum_qm_plan", default: 0.0
|
t.float "costum_qm_plan", default: 0.0
|
||||||
t.float "cost", default: 0.0
|
t.float "cost", default: 0.0
|
||||||
t.float "cost_qm", default: 0.0
|
t.float "cost_qm", default: 0.0
|
||||||
t.boolean "privacy_policy_accepted", default: false
|
t.boolean "privacy_policy", default: false
|
||||||
|
t.boolean "created_by_operator", default: false
|
||||||
t.datetime "created_at", null: false
|
t.datetime "created_at", null: false
|
||||||
t.datetime "updated_at", null: false
|
t.datetime "updated_at", null: false
|
||||||
t.index ["costumer_id"], name: "index_jobs_on_costumer_id"
|
t.index ["cashier_id"], name: "index_jobs_on_cashier_id"
|
||||||
|
t.index ["creator_id"], name: "index_jobs_on_creator_id"
|
||||||
|
t.index ["customer_id"], name: "index_jobs_on_customer_id"
|
||||||
t.index ["operator_id"], name: "index_jobs_on_operator_id"
|
t.index ["operator_id"], name: "index_jobs_on_operator_id"
|
||||||
t.index ["status"], name: "index_jobs_on_status"
|
t.index ["status"], name: "index_jobs_on_status"
|
||||||
end
|
end
|
||||||
@@ -83,8 +88,12 @@ ActiveRecord::Schema[7.2].define(version: 2024_08_26_144016) do
|
|||||||
t.string "password_digest", null: false
|
t.string "password_digest", null: false
|
||||||
t.string "firstname"
|
t.string "firstname"
|
||||||
t.string "lastname"
|
t.string "lastname"
|
||||||
t.integer "role", default: 0
|
t.string "role", default: "user"
|
||||||
t.boolean "verified", default: false, null: false
|
t.boolean "verified", default: false, null: false
|
||||||
|
t.integer "customer_jobs_count", default: 0
|
||||||
|
t.integer "operator_jobs_count", default: 0
|
||||||
|
t.integer "created_jobs_count", default: 0
|
||||||
|
t.integer "cashed_jobs_count", default: 0
|
||||||
t.datetime "created_at", null: false
|
t.datetime "created_at", null: false
|
||||||
t.datetime "updated_at", null: false
|
t.datetime "updated_at", null: false
|
||||||
t.index ["email"], name: "index_users_on_email", unique: true
|
t.index ["email"], name: "index_users_on_email", unique: true
|
||||||
@@ -93,7 +102,9 @@ ActiveRecord::Schema[7.2].define(version: 2024_08_26_144016) do
|
|||||||
|
|
||||||
add_foreign_key "active_storage_attachments", "active_storage_blobs", column: "blob_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 "active_storage_variant_records", "active_storage_blobs", column: "blob_id"
|
||||||
add_foreign_key "jobs", "users", column: "costumer_id"
|
add_foreign_key "jobs", "users", column: "cashier_id"
|
||||||
|
add_foreign_key "jobs", "users", column: "creator_id"
|
||||||
|
add_foreign_key "jobs", "users", column: "customer_id"
|
||||||
add_foreign_key "jobs", "users", column: "operator_id"
|
add_foreign_key "jobs", "users", column: "operator_id"
|
||||||
add_foreign_key "sessions", "users"
|
add_foreign_key "sessions", "users"
|
||||||
end
|
end
|
||||||
|
|||||||
153
db/seeds.rb
153
db/seeds.rb
@@ -10,28 +10,157 @@
|
|||||||
|
|
||||||
Faker::Config.locale = :de
|
Faker::Config.locale = :de
|
||||||
|
|
||||||
# Admin
|
# Admins
|
||||||
User.create!(email: "david.boehm@hs-rm.de", firstname: "David", lastname: "Böhm", role: :admin, password_digest: BCrypt::Password.create("admin"), verified: true)
|
User.create!(email: "david.boehm@hs-rm.de", firstname: "David", lastname: "Böhm", role: :admin, password_digest: BCrypt::Password.create("admin"), verified: true)
|
||||||
|
User.create!(email: "maximilian.lasser@hs-rm.de", firstname: "Max", lastname: "Lasser", role: :admin, password_digest: BCrypt::Password.create("admin"), verified: true)
|
||||||
|
|
||||||
|
# Operators
|
||||||
|
operators = []
|
||||||
|
operators << User.create!(email: "tutor.operator@hs-rm.de", firstname: "Tutor", lastname: "Operator", role: :operator, password_digest: BCrypt::Password.create("operator"), verified: true)
|
||||||
|
operators << User.create!(email: "tutor2.operator@hs-rm.de", firstname: "Tutor2", lastname: "Operator", role: :operator, password_digest: BCrypt::Password.create("operator"), verified: true)
|
||||||
|
|
||||||
# Students
|
# Students
|
||||||
|
User.create!(email: "stud.student@student.hs-rm.de", firstname: "Student", lastname: "Student", password_digest: BCrypt::Password.create("stud"), verified: true)
|
||||||
|
User.create!(email: "stud2.student@student.hs-rm.de", firstname: "Student2", lastname: "Student", password_digest: BCrypt::Password.create("stud"), verified: true)
|
||||||
|
|
||||||
|
# Students with jobs
|
||||||
students = []
|
students = []
|
||||||
5.times do
|
10.times do
|
||||||
firstname = Faker::Name.unique.first_name
|
firstname = Faker::Name.unique.first_name
|
||||||
lastname = Faker::Name.unique.last_name
|
lastname = Faker::Name.unique.last_name
|
||||||
students << User.new(email: firstname + "." + lastname + "@student.hs-rm.de", firstname: firstname, lastname: lastname, password_digest: BCrypt::Password.create("password"), verified: true)
|
# created_at = Faker::Time.backward(days: 60, period: :day)
|
||||||
|
created_at = Faker::Time.between_dates(from: Date.today - 60, to: Date.today - 30, period: :day)
|
||||||
|
email=I18n.transliterate "#{firstname}.#{lastname}@student.hs-rm.de"
|
||||||
|
puts "Create Student: " + email
|
||||||
|
students << User.new(email: email, firstname: firstname, lastname: lastname, password_digest: BCrypt::Password.create("password"), verified: true, created_at: created_at)
|
||||||
students.last.save!
|
students.last.save!
|
||||||
end
|
end
|
||||||
|
|
||||||
[ 'GanzWichtig.pdf', 'IchBinIn5MinDran.pdf', 'DerPlanDerImmerProblemeMacht.pdf',
|
# Students without jobs
|
||||||
'DieFarbenGefallenMirNicht.pdf', 'MachHinIchHabsEilig.pdf', 'WarumDauertDasSoLange.pdf',
|
100.times do
|
||||||
'DenPlanBezahleIchNicht.pdf', 'IchWarAlsErstesDran.pdf', 'WarumIstDerPlotterDefekt.pdf',
|
firstname = Faker::Name.unique.first_name
|
||||||
'DasNächsteMalGeheIchWoAndersHin.pdf' ].shuffle.each do |pdf|
|
lastname = Faker::Name.unique.last_name
|
||||||
status = %i[open open open open open printing pickup paid canceled].sample
|
created_at = Faker::Time.backward(days: 60, period: :day)
|
||||||
|
# created_at = Faker::Time.between_dates(from: Date.today - 60, to: Date.today, period: :day)
|
||||||
|
email=I18n.transliterate "#{firstname}.#{lastname}@student.hs-rm.de"
|
||||||
|
puts "Create Student: " + email
|
||||||
|
User.new(email: email, firstname: firstname, lastname: lastname, password_digest: BCrypt::Password.create("password"), verified: true, created_at: created_at).save!
|
||||||
|
end
|
||||||
|
|
||||||
job = Job.new(costumer_firstname: Faker::Name.unique.first_name, costumer_lastname: Faker::Name.unique.last_name,
|
# Students without jobs not validated email
|
||||||
costumer_id: students[rand(0...4)].id,
|
10.times do
|
||||||
# number_of_plans_a0: a0, number_of_plans_a1: a1, number_of_plans_a2: a2, number_of_plans_a3: a3,
|
firstname = Faker::Name.unique.first_name
|
||||||
status:, privacy_policy_accepted: true)
|
lastname = Faker::Name.unique.last_name
|
||||||
|
created_at = Faker::Time.backward(days: 60, period: :day)
|
||||||
|
# created_at = Faker::Time.between_dates(from: Date.today - 60, to: Date.today, period: :day)
|
||||||
|
email=I18n.transliterate "#{firstname}.#{lastname}@student.hs-rm.de"
|
||||||
|
puts "Create Student: " + email
|
||||||
|
User.new(email: email, firstname: firstname, lastname: lastname, password_digest: BCrypt::Password.create("password"), verified: false, created_at: created_at).save!
|
||||||
|
end
|
||||||
|
|
||||||
|
# Jobs paid (and some canceled) in the far past
|
||||||
|
10.times do
|
||||||
|
[ 'GanzWichtig.pdf', 'IchBinIn5MinDran.pdf', 'DerPlanDerImmerProblemeMacht.pdf',
|
||||||
|
'DieFarbenGefallenMirNicht.pdf', 'MachHinIchHabsEilig.pdf', 'WarumDauertDasSoLange.pdf',
|
||||||
|
'DenPlanBezahleIchNicht.pdf', 'IchWarAlsErstesDran.pdf', 'WarumIstDerPlotterDefekt.pdf',
|
||||||
|
'DasNächsteMalGeheIchWoAndersHin.pdf' ].shuffle.each do |pdf|
|
||||||
|
status = %i[paid paid paid paid paid paid paid canceled].sample
|
||||||
|
created_at = Faker::Time.backward(days: 1.year.in_days, period: :day)
|
||||||
|
if status == :paid
|
||||||
|
printed_at = created_at + 30.minutes
|
||||||
|
paid_at = created_at + 45.minutes
|
||||||
|
status_changed_at = paid_at
|
||||||
|
updated_at = status_changed_at
|
||||||
|
else
|
||||||
|
updated_at = created_at + rand(4..44).minutes
|
||||||
|
status_changed_at = updated_at
|
||||||
|
end
|
||||||
|
job = Job.new(status:, privacy_policy: true)
|
||||||
|
job.pdf = File.open(Rails.root.join('db/pdfs/', pdf))
|
||||||
|
student = students[rand(0..9)]
|
||||||
|
job.customer = student
|
||||||
|
job.creator = student
|
||||||
|
operator = operators[rand(0...1)]
|
||||||
|
job.operator = operator if status != :open
|
||||||
|
job.cashier = operator if status == :paid
|
||||||
|
job.save!
|
||||||
|
job.update_column :created_at, created_at # write with update_column to avoid before_save action
|
||||||
|
job.update_column :printed_at, printed_at # write with update_column to avoid before_save action
|
||||||
|
job.update_column :status_changed_at, status_changed_at # write with update_column to avoid before_save action
|
||||||
|
job.update_column :paid_at, paid_at if status == :paid # write with update_column to avoid before_save action
|
||||||
|
job.update_column :updated_at, updated_at # write with update_column to avoid before_save action
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
# Jobs paid (and some canceled) in the past
|
||||||
|
2.times do
|
||||||
|
[ 'GanzWichtig.pdf', 'IchBinIn5MinDran.pdf', 'DerPlanDerImmerProblemeMacht.pdf',
|
||||||
|
'DieFarbenGefallenMirNicht.pdf', 'MachHinIchHabsEilig.pdf', 'WarumDauertDasSoLange.pdf',
|
||||||
|
'DenPlanBezahleIchNicht.pdf', 'IchWarAlsErstesDran.pdf', 'WarumIstDerPlotterDefekt.pdf',
|
||||||
|
'DasNächsteMalGeheIchWoAndersHin.pdf' ].shuffle.each do |pdf|
|
||||||
|
status = %i[paid paid paid paid paid paid paid canceled].sample
|
||||||
|
created_at = Faker::Time.backward(days: 5, period: :day)
|
||||||
|
if status == :paid
|
||||||
|
printed_at = created_at + 30.minutes
|
||||||
|
paid_at = created_at + 45.minutes
|
||||||
|
status_changed_at = paid_at
|
||||||
|
updated_at = status_changed_at
|
||||||
|
else
|
||||||
|
updated_at = created_at + rand(4..44).minutes
|
||||||
|
status_changed_at = updated_at
|
||||||
|
end
|
||||||
|
job = Job.new(status:, privacy_policy: true)
|
||||||
|
job.pdf = File.open(Rails.root.join('db/pdfs/', pdf))
|
||||||
|
student = students[rand(0...9)]
|
||||||
|
job.customer = student
|
||||||
|
job.creator = student
|
||||||
|
operator = operators[rand(0...1)]
|
||||||
|
job.operator = operator if status == :paid
|
||||||
|
job.cashier = operator if status == :paid
|
||||||
|
job.save!
|
||||||
|
job.update_column :created_at, created_at # write with update_column to avoid before_save action
|
||||||
|
job.update_column :printed_at, printed_at # write with update_column to avoid before_save action
|
||||||
|
job.update_column :status_changed_at, status_changed_at # write with update_column to avoid before_save action
|
||||||
|
job.update_column :paid_at, paid_at if status == :paid # write with update_column to avoid before_save action
|
||||||
|
job.update_column :updated_at, updated_at # write with update_column to avoid before_save action
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Jobs
|
||||||
|
3.times do |i|
|
||||||
|
status_pool = %i[canceled open open printing printing pickup pickup paid paid paid]
|
||||||
|
[ 'GanzWichtig.pdf', 'IchBinIn5MinDran.pdf', 'DerPlanDerImmerProblemeMacht.pdf',
|
||||||
|
'DieFarbenGefallenMirNicht.pdf', 'MachHinIchHabsEilig.pdf', 'WarumDauertDasSoLange.pdf',
|
||||||
|
'DenPlanBezahleIchNicht.pdf', 'IchWarAlsErstesDran.pdf', 'WarumIstDerPlotterDefekt.pdf',
|
||||||
|
'DasNächsteMalGeheIchWoAndersHin.pdf' ].shuffle.each do |pdf|
|
||||||
|
status = status_pool.pop
|
||||||
|
status = :open if i > 0
|
||||||
|
job = Job.new(status:, privacy_policy: true)
|
||||||
|
job.pdf = File.open(Rails.root.join('db/pdfs/', pdf))
|
||||||
|
student = students[rand(0...4)]
|
||||||
|
job.customer = student
|
||||||
|
job.creator = student
|
||||||
|
operator = operators[rand(0...1)]
|
||||||
|
job.operator = operator if status != :open
|
||||||
|
job.cashier = operator if status == :paid
|
||||||
|
job.save!
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Jobs created from operator
|
||||||
|
[ 'GanzWichtig.pdf', 'IchBinIn5MinDran.pdf', 'DerPlanDerImmerProblemeMacht.pdf',
|
||||||
|
'DieFarbenGefallenMirNicht.pdf', 'MachHinIchHabsEilig.pdf', 'WarumDauertDasSoLange.pdf',
|
||||||
|
'DenPlanBezahleIchNicht.pdf', 'IchWarAlsErstesDran.pdf', 'WarumIstDerPlotterDefekt.pdf',
|
||||||
|
'DasNächsteMalGeheIchWoAndersHin.pdf' ].shuffle.each do |pdf|
|
||||||
|
job = Job.new(privacy_policy: true)
|
||||||
job.pdf = File.open(Rails.root.join('db/pdfs/', pdf))
|
job.pdf = File.open(Rails.root.join('db/pdfs/', pdf))
|
||||||
|
student = students[rand(0...9)]
|
||||||
|
job.customer = [ student, student, false ].sample
|
||||||
|
job.customer_firstname = student.firstname
|
||||||
|
job.customer_lastname = student.lastname
|
||||||
|
job.creator = operators[rand(0...1)]
|
||||||
|
job.created_by_operator = true
|
||||||
|
job.inspect
|
||||||
job.save!
|
job.save!
|
||||||
end
|
end
|
||||||
|
|||||||
8
test/controllers/admin/dashboard_controller_test.rb
Normal file
8
test/controllers/admin/dashboard_controller_test.rb
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
require "test_helper"
|
||||||
|
|
||||||
|
class Admin::DashboardControllerTest < ActionDispatch::IntegrationTest
|
||||||
|
test "should get index" do
|
||||||
|
get admin_dashboard_index_url
|
||||||
|
assert_response :success
|
||||||
|
end
|
||||||
|
end
|
||||||
8
test/controllers/admin/jobs_controller_test.rb
Normal file
8
test/controllers/admin/jobs_controller_test.rb
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
require "test_helper"
|
||||||
|
|
||||||
|
class Admin::JobsControllerTest < ActionDispatch::IntegrationTest
|
||||||
|
test "should get index" do
|
||||||
|
get admin_jobs_index_url
|
||||||
|
assert_response :success
|
||||||
|
end
|
||||||
|
end
|
||||||
33
test/controllers/admin/users_controller_test.rb
Normal file
33
test/controllers/admin/users_controller_test.rb
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
require "test_helper"
|
||||||
|
|
||||||
|
class Admin::UsersControllerTest < ActionDispatch::IntegrationTest
|
||||||
|
test "should get index" do
|
||||||
|
get admin_users_index_url
|
||||||
|
assert_response :success
|
||||||
|
end
|
||||||
|
|
||||||
|
test "should get edit" do
|
||||||
|
get admin_users_edit_url
|
||||||
|
assert_response :success
|
||||||
|
end
|
||||||
|
|
||||||
|
test "should get show" do
|
||||||
|
get admin_users_show_url
|
||||||
|
assert_response :success
|
||||||
|
end
|
||||||
|
|
||||||
|
test "should get new" do
|
||||||
|
get admin_users_new_url
|
||||||
|
assert_response :success
|
||||||
|
end
|
||||||
|
|
||||||
|
test "should get create" do
|
||||||
|
get admin_users_create_url
|
||||||
|
assert_response :success
|
||||||
|
end
|
||||||
|
|
||||||
|
test "should get update" do
|
||||||
|
get admin_users_update_url
|
||||||
|
assert_response :success
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -17,7 +17,7 @@ class JobsControllerTest < ActionDispatch::IntegrationTest
|
|||||||
|
|
||||||
test "should create job" do
|
test "should create job" do
|
||||||
assert_difference("Job.count") do
|
assert_difference("Job.count") do
|
||||||
post jobs_url, params: { job: { cost_center: @job.cost_center, costum_qm_plan: @job.costum_qm_plan, costumer_firstname: @job.costumer_firstname, costumer_id_id: @job.costumer_id_id, costumer_lastname: @job.costumer_lastname, intern: @job.intern, number_of_plans_a0: @job.number_of_plans_a0, number_of_plans_a1: @job.number_of_plans_a1, number_of_plans_a2: @job.number_of_plans_a2, number_of_plans_a3: @job.number_of_plans_a3, operator_firstname: @job.operator_firstname, operator_id_id: @job.operator_id_id, operator_lastname: @job.operator_lastname, paid: @job.paid, printed_at: @job.printed_at } }
|
post jobs_url, params: { job: { cost_center: @job.cost_center, costum_qm_plan: @job.costum_qm_plan, customer_firstname: @job.customer_firstname, customer_id_id: @job.customer_id_id, customer_lastname: @job.customer_lastname, intern: @job.intern, number_of_plans_a0: @job.number_of_plans_a0, number_of_plans_a1: @job.number_of_plans_a1, number_of_plans_a2: @job.number_of_plans_a2, number_of_plans_a3: @job.number_of_plans_a3, operator_firstname: @job.operator_firstname, operator_id_id: @job.operator_id_id, operator_lastname: @job.operator_lastname, paid: @job.paid, printed_at: @job.printed_at } }
|
||||||
end
|
end
|
||||||
|
|
||||||
assert_redirected_to job_url(Job.last)
|
assert_redirected_to job_url(Job.last)
|
||||||
@@ -34,7 +34,7 @@ class JobsControllerTest < ActionDispatch::IntegrationTest
|
|||||||
end
|
end
|
||||||
|
|
||||||
test "should update job" do
|
test "should update job" do
|
||||||
patch job_url(@job), params: { job: { cost_center: @job.cost_center, costum_qm_plan: @job.costum_qm_plan, costumer_firstname: @job.costumer_firstname, costumer_id_id: @job.costumer_id_id, costumer_lastname: @job.costumer_lastname, intern: @job.intern, number_of_plans_a0: @job.number_of_plans_a0, number_of_plans_a1: @job.number_of_plans_a1, number_of_plans_a2: @job.number_of_plans_a2, number_of_plans_a3: @job.number_of_plans_a3, operator_firstname: @job.operator_firstname, operator_id_id: @job.operator_id_id, operator_lastname: @job.operator_lastname, paid: @job.paid, printed_at: @job.printed_at } }
|
patch job_url(@job), params: { job: { cost_center: @job.cost_center, costum_qm_plan: @job.costum_qm_plan, customer_firstname: @job.customer_firstname, customer_id_id: @job.customer_id_id, customer_lastname: @job.customer_lastname, intern: @job.intern, number_of_plans_a0: @job.number_of_plans_a0, number_of_plans_a1: @job.number_of_plans_a1, number_of_plans_a2: @job.number_of_plans_a2, number_of_plans_a3: @job.number_of_plans_a3, operator_firstname: @job.operator_firstname, operator_id_id: @job.operator_id_id, operator_lastname: @job.operator_lastname, paid: @job.paid, printed_at: @job.printed_at } }
|
||||||
assert_redirected_to job_url(@job)
|
assert_redirected_to job_url(@job)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
18
test/controllers/profiles_controller_test.rb
Normal file
18
test/controllers/profiles_controller_test.rb
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
require "test_helper"
|
||||||
|
|
||||||
|
class ProfilesControllerTest < ActionDispatch::IntegrationTest
|
||||||
|
test "should get show" do
|
||||||
|
get profiles_show_url
|
||||||
|
assert_response :success
|
||||||
|
end
|
||||||
|
|
||||||
|
test "should get edit" do
|
||||||
|
get profiles_edit_url
|
||||||
|
assert_response :success
|
||||||
|
end
|
||||||
|
|
||||||
|
test "should get destroy" do
|
||||||
|
get profiles_destroy_url
|
||||||
|
assert_response :success
|
||||||
|
end
|
||||||
|
end
|
||||||
12
test/fixtures/jobs.yml
vendored
12
test/fixtures/jobs.yml
vendored
@@ -2,11 +2,11 @@
|
|||||||
|
|
||||||
one:
|
one:
|
||||||
operator_id: one
|
operator_id: one
|
||||||
costumer_id: one
|
customer_id: one
|
||||||
operator_firstname: MyString
|
operator_firstname: MyString
|
||||||
operator_lastname: MyString
|
operator_lastname: MyString
|
||||||
costumer_firstname: MyString
|
customer_firstname: MyString
|
||||||
costumer_lastname: MyString
|
customer_lastname: MyString
|
||||||
paid: false
|
paid: false
|
||||||
printed_at: 2024-07-27 12:13:47
|
printed_at: 2024-07-27 12:13:47
|
||||||
intern: false
|
intern: false
|
||||||
@@ -19,11 +19,11 @@ one:
|
|||||||
|
|
||||||
two:
|
two:
|
||||||
operator_id: two
|
operator_id: two
|
||||||
costumer_id: two
|
customer_id: two
|
||||||
operator_firstname: MyString
|
operator_firstname: MyString
|
||||||
operator_lastname: MyString
|
operator_lastname: MyString
|
||||||
costumer_firstname: MyString
|
customer_firstname: MyString
|
||||||
costumer_lastname: MyString
|
customer_lastname: MyString
|
||||||
paid: false
|
paid: false
|
||||||
printed_at: 2024-07-27 12:13:47
|
printed_at: 2024-07-27 12:13:47
|
||||||
intern: false
|
intern: false
|
||||||
|
|||||||
13
test/policies/admin/dashboard_policy_test.rb
Normal file
13
test/policies/admin/dashboard_policy_test.rb
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
require "test_helper"
|
||||||
|
|
||||||
|
# See https://actionpolicy.evilmartians.io/#/testing?id=testing-policies
|
||||||
|
class Admin::DashboardPolicyTest < ActiveSupport::TestCase
|
||||||
|
def test_index
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_create
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_manage
|
||||||
|
end
|
||||||
|
end
|
||||||
13
test/policies/admin/job_policy_test.rb
Normal file
13
test/policies/admin/job_policy_test.rb
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
require "test_helper"
|
||||||
|
|
||||||
|
# See https://actionpolicy.evilmartians.io/#/testing?id=testing-policies
|
||||||
|
class Admin::JobPolicyTest < ActiveSupport::TestCase
|
||||||
|
def test_index
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_create
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_manage
|
||||||
|
end
|
||||||
|
end
|
||||||
13
test/policies/admin/user_policy_test.rb
Normal file
13
test/policies/admin/user_policy_test.rb
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
require "test_helper"
|
||||||
|
|
||||||
|
# See https://actionpolicy.evilmartians.io/#/testing?id=testing-policies
|
||||||
|
class Admin::UserPolicyTest < ActiveSupport::TestCase
|
||||||
|
def test_index
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_create
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_manage
|
||||||
|
end
|
||||||
|
end
|
||||||
13
test/policies/job_policy_test.rb
Normal file
13
test/policies/job_policy_test.rb
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
require "test_helper"
|
||||||
|
|
||||||
|
# See https://actionpolicy.evilmartians.io/#/testing?id=testing-policies
|
||||||
|
class JobPolicyTest < ActiveSupport::TestCase
|
||||||
|
def test_index
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_create
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_manage
|
||||||
|
end
|
||||||
|
end
|
||||||
13
test/policies/operator/job_policy_test.rb
Normal file
13
test/policies/operator/job_policy_test.rb
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
require "test_helper"
|
||||||
|
|
||||||
|
# See https://actionpolicy.evilmartians.io/#/testing?id=testing-policies
|
||||||
|
class Operator::JobPolicyTest < ActiveSupport::TestCase
|
||||||
|
def test_index
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_create
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_manage
|
||||||
|
end
|
||||||
|
end
|
||||||
13
test/policies/session_policy_test.rb
Normal file
13
test/policies/session_policy_test.rb
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
require "test_helper"
|
||||||
|
|
||||||
|
# See https://actionpolicy.evilmartians.io/#/testing?id=testing-policies
|
||||||
|
class SessionPolicyTest < ActiveSupport::TestCase
|
||||||
|
def test_index
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_create
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_manage
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -16,9 +16,9 @@ class JobsTest < ApplicationSystemTestCase
|
|||||||
|
|
||||||
fill_in "Cost center", with: @job.cost_center
|
fill_in "Cost center", with: @job.cost_center
|
||||||
fill_in "Costum qm plan", with: @job.costum_qm_plan
|
fill_in "Costum qm plan", with: @job.costum_qm_plan
|
||||||
fill_in "Costumer firstname", with: @job.costumer_firstname
|
fill_in "customer firstname", with: @job.customer_firstname
|
||||||
fill_in "Costumer id", with: @job.costumer_id_id
|
fill_in "customer id", with: @job.customer_id_id
|
||||||
fill_in "Costumer lastname", with: @job.costumer_lastname
|
fill_in "customer lastname", with: @job.customer_lastname
|
||||||
check "Intern" if @job.intern
|
check "Intern" if @job.intern
|
||||||
fill_in "Number of plans a0", with: @job.number_of_plans_a0
|
fill_in "Number of plans a0", with: @job.number_of_plans_a0
|
||||||
fill_in "Number of plans a1", with: @job.number_of_plans_a1
|
fill_in "Number of plans a1", with: @job.number_of_plans_a1
|
||||||
@@ -41,9 +41,9 @@ class JobsTest < ApplicationSystemTestCase
|
|||||||
|
|
||||||
fill_in "Cost center", with: @job.cost_center
|
fill_in "Cost center", with: @job.cost_center
|
||||||
fill_in "Costum qm plan", with: @job.costum_qm_plan
|
fill_in "Costum qm plan", with: @job.costum_qm_plan
|
||||||
fill_in "Costumer firstname", with: @job.costumer_firstname
|
fill_in "customer firstname", with: @job.customer_firstname
|
||||||
fill_in "Costumer id", with: @job.costumer_id_id
|
fill_in "customer id", with: @job.customer_id_id
|
||||||
fill_in "Costumer lastname", with: @job.costumer_lastname
|
fill_in "customer lastname", with: @job.customer_lastname
|
||||||
check "Intern" if @job.intern
|
check "Intern" if @job.intern
|
||||||
fill_in "Number of plans a0", with: @job.number_of_plans_a0
|
fill_in "Number of plans a0", with: @job.number_of_plans_a0
|
||||||
fill_in "Number of plans a1", with: @job.number_of_plans_a1
|
fill_in "Number of plans a1", with: @job.number_of_plans_a1
|
||||||
|
|||||||
Reference in New Issue
Block a user